• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
9
Question by jimbeau · May 28, 2013 at 07:17 PM · animationcurvebeziertangent

What is the math behind AnimationCurve.Evaluate?

I understand how to use animation curves in Unity, but I'm more interested in how Unity actually evaluates an animation curve at a given point. In other words, what is the math behind the function Evaluate?

The reason I ask is that I have a lot of animation data in animation curve format: time, value, in tangent, out tangent. I want to convert this data into splines like bezier curves or other functions, but I am not sure what the formula for this conversion would be.

Anyone have ideas?

Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Benproductions1 · May 29, 2013 at 01:59 AM 0
Share

It uses Bezier Curves, like it should. If you want to evaluate those, you can do a quick google search :)

avatar image Varaughe · Aug 06, 2013 at 01:49 AM 0
Share

well of course is bezier curves(which can be represented as hermit also),but it's not that cubic bezier curve,which anyone knows,I mean the factors are particular for the unity implementation ... at a moment I also thought they are using only trigonometric function ... whichever way,it would be of great help the exact formula

avatar image Varaughe · Dec 30, 2016 at 06:07 PM 0
Share

If this is still an issue in 2017 , you could check out the Runtime Curve Editor. All the sources are available in that package, so the equation, by which that curve is plotted, is also available. Of course , the package has more to offer than just plotting a curve by the equation you are looking for .

avatar image TheNoobieWaffle · Aug 17, 2017 at 03:29 AM 0
Share

Unity's AnimationCurve lets you modify the tangets by moving that little handle. What if I wanted to make my own class similar to animation Curve, but I wanted to set the tangents with a vector2 ins$$anonymous$$d of the handle that then in turn calculated the tangents? How could I evauluate that, keeping in $$anonymous$$d that there could be 3 intersections?

5 Replies

· Add your reply
  • Sort: 
avatar image
7

Answer by Varaughe · Aug 06, 2013 at 03:21 AM

If you want to know what is the exact equation behind an AnimationCurve, you should check Runtime Curve Editor (from Unity Asset Store). The package replicates 100% the equation by which the Animation Curve built-in editor plots the curve.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
7

Answer by Paulius-Liekis · Aug 06, 2013 at 09:10 AM

It should be something like this:

 float Evaluate(float t, Keyframe keyframe0, Keyframe keyframe1)
 {
     float dt = keyframe1.time - keyframe0.time;
     
     float m0 = keyframe0.outTangent * dt;
     float m1 = keyframe1.inTangent * dt;
 
     float t2 = t * t;
     float t3 = t2 * t;
     
     float a = 2 * t3 - 3 * t2 + 1;
     float b = t3 - 2 * t2 + t;
     float c = t3 - t2;
     float d = -2 * t3 + 3 * t2;
     
     return a * keyframe0.value + b * m0 + c * m1 + d * keyframe1.value;
 }
Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Varaughe · Aug 06, 2013 at 10:16 AM 0
Share

have you tried this one,did you drawn twice the curve ?, me I drawn the curve twice,once using directly the evaluate method from unity and once with the formula I explained above your comment ... and the curves are matching 99,9%..of course the tangents needs scaling with the aspect ratio ... what I see strange in your method, is that you evaluate by 't' :) ... the unity evaluates by time...so perhaps from that time it's finding the 't' and then back the keyframe.value ... in my case ,what I needed was just to have bezier curve exactly matching the curve drawn by unity

avatar image Paulius-Liekis · Aug 06, 2013 at 11:46 AM 1
Share

t is from 0 to 1 in this case, i.e. t = $$anonymous$$athf.InverseLerp(keyframe0.time, keyframe1.time, time)

avatar image Paulius-Liekis · Aug 06, 2013 at 11:49 AM 0
Share

No, I haven't tried it myself. I copied this function from one of my projects (this is slightly modified version).

As far as I remember Unity uses this kind of code (a bit more optimized).

avatar image majakthecoder · Aug 01, 2014 at 07:58 PM 0
Share

What you wrote is just regular Cubic Hermite spline with tangents defined by hand. The same curve is default interpolation curve in 3d studio max (TCB controler - parameters Tension, Continuity, Bias are used to calculate tangents)

avatar image infernobirdy · Dec 22, 2017 at 01:35 PM 1
Share

Hey guys! Thanks for this, works perfectly! If you want it to work with more than 2 keyframes or if the first and last keyframe are not exactly 0 and 1 just add this line to normalize t:

t = (t - keyframe0.time) / dt;

Show more comments
avatar image
3

Answer by SuperPingu · Feb 03, 2016 at 03:39 PM

Unity define a curve with 2 keyframes, each composed of a point and a tangent. I guess the simplest curve matching that is a third degree polynomial (a cubic function). Given the 2 points and tangents, it is possible to compute the polynomial coefficients simply by solving the following equation system:

 (1)  a*p1x^3 + b*p1x^2 + c*p1x + d = p1y
 (2)  a*p2x^3 + b*p2x^2 + c*p2x + d = p2y
 (3)  3*a*p1x^2 + 2*b*p1x + c = tp1
 (4)  3*a*p2x^2 + 2*b*p2x + c = tp2

You can solve this manually or using a computer algebra system.

This gives you:

 float a = (p1x * tp1 + p1x * tp2 - p2x * tp1 - p2x * tp2 - 2 * p1y + 2 * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x);
 float b = ((-p1x * p1x * tp1 - 2 * p1x * p1x * tp2 + 2 * p2x * p2x * tp1 + p2x * p2x * tp2 - p1x * p2x * tp1 + p1x * p2x * tp2 + 3 * p1x * p1y - 3 * p1x * p2y + 3 * p1y * p2x - 3 * p2x * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x));
 float c = ((p1x * p1x * p1x * tp2 - p2x * p2x * p2x * tp1 - p1x * p2x * p2x * tp1 - 2 * p1x * p2x * p2x * tp2 + 2 * p1x * p1x * p2x * tp1 + p1x * p1x * p2x * tp2 - 6 * p1x * p1y * p2x + 6 * p1x * p2x * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x));
 float d = ((p1x * p2x * p2x * p2x * tp1 - p1x * p1x * p2x * p2x * tp1 + p1x * p1x * p2x * p2x * tp2 - p1x * p1x * p1x * p2x * tp2 - p1y * p2x * p2x * p2x + p1x * p1x * p1x * p2y + 3 * p1x * p1y * p2x * p2x - 3 * p1x * p1x * p2x * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x));
 

Then, to evaluate the value:

 float Evaluate(float t)
 {
     return a*t*t*t + b*t*t + c*t + d;
 }

I checked with Unity with the following quick and dirty code:

 using UnityEngine;

 [ExecuteInEditMode]
 public class TestAnimCurve : MonoBehaviour {
     public AnimationCurve anim = AnimationCurve.EaseInOut(0, 0, 1, 1);
     float a;
     float b;
     float c;
     float d;
     void Update () {
         float p1x= anim.keys[0].time;
         float p1y= anim.keys[0].value;
         float tp1=anim.keys[0].outTangent;
         float p2x=anim.keys[1].time;
         float p2y= anim.keys[1].value;
         float tp2= anim.keys[1].inTangent;
         Debug.Log(p1x+ ", " + p1y+ ", " + tp1 + ", " + p2x + ", " + p2y + ", " + tp2);
         Debug.Log("Evaluate Unity: " + anim.Evaluate(0.1f) + ", " + anim.Evaluate(0.2f) + ", " + anim.Evaluate(0.3f) + ", " + anim.Evaluate(0.4f) + ", " + anim.Evaluate(0.5f) + ", " + anim.Evaluate(0.6f) + ", " + anim.Evaluate(0.76f) + ", " + anim.Evaluate(0.88f) + ", " + anim.Evaluate(0.98f));
         a = (p1x * tp1 + p1x * tp2 - p2x * tp1 - p2x * tp2 - 2 * p1y + 2 * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x);
         b = ((-p1x * p1x * tp1 - 2 * p1x * p1x * tp2 + 2 * p2x * p2x * tp1 + p2x * p2x * tp2 - p1x * p2x * tp1 + p1x * p2x * tp2 + 3 * p1x * p1y - 3 * p1x * p2y + 3 * p1y * p2x - 3 * p2x * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x));
         c = ((p1x * p1x * p1x * tp2 - p2x * p2x * p2x * tp1 - p1x * p2x * p2x * tp1 - 2 * p1x * p2x * p2x * tp2 + 2 * p1x * p1x * p2x * tp1 + p1x * p1x * p2x * tp2 - 6 * p1x * p1y * p2x + 6 * p1x * p2x * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x));
         d = ((p1x * p2x * p2x * p2x * tp1 - p1x * p1x * p2x * p2x * tp1 + p1x * p1x * p2x * p2x * tp2 - p1x * p1x * p1x * p2x * tp2 - p1y * p2x * p2x * p2x + p1x * p1x * p1x * p2y + 3 * p1x * p1y * p2x * p2x - 3 * p1x * p1x * p2x * p2y) / (p1x * p1x * p1x - p2x * p2x * p2x + 3 * p1x * p2x * p2x - 3 * p1x * p1x * p2x));
         Debug.Log("Evaluate Cubic: " + Evaluate(0.1f) + ", " + Evaluate(0.2f) + ", " + Evaluate(0.3f) + ", " + Evaluate(0.4f) + ", " + Evaluate(0.5f) + ", " + Evaluate(0.6f) + ", " + Evaluate(0.76f) + ", " + Evaluate(0.88f) + ", " + anim.Evaluate(0.98f));
     }
     float Evaluate(float t)
     {
         return a * t * t * t + b * t * t + c * t + d;
     }
   }

After modifing tangents of the animation curve, the debug messages produced by this code are:

 0, 0, -4.484611, 1, 1, -10.23884
 Evaluate Unity: -0.2431039, -0.1423873, 0.2018093, 0.6891449, 1.219279, 1.691871, 2.077879, 1.854902, 1.193726
 Evaluate Cubic: -0.2431039, -0.1423873, 0.2018092, 0.6891448, 1.219279, 1.691871, 2.077879, 1.854902, 1.193726

So it really seams that this approach is the math behind AnimationCurve.Evaluate ;)

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image keenanwoodall · Nov 14, 2018 at 03:00 AM 0
Share

Great work! Thanks to your code I was able to figure out how to get animation curves working with the job system. The only thing missing is weights (to affect the slope of the previous to current or current to next key) Do you have any pointers as to how to support weights?

avatar image DaNerdyDude keenanwoodall · Dec 01, 2020 at 12:26 AM 0
Share

@keenanwoodall I know this reply is a couple years late, but I'm putting this here for anyone else who wants to see it too. As far as my testing has gone, the weights have zero affect on the maths of the equation.

$$anonymous$$y guess is that they were originally intended as a way for users to manually weigh each point to their liking, but would have made the mathematics far more complicated than necessary for a feature that wouldn't have been that useful.

avatar image DaNerdyDude · Nov 28, 2020 at 05:59 AM 0
Share

I did some algebra myself to factorise the equations for a, b, c and d just to make the code a bit faster and a bit easier to read:

 float divisor = ((p1x * p1x * p1x) - (p2x * p2x * p2x) + (3 * p1x * p2x * (p2x - p1x)));
 
 float a = ((tp1 + tp2) * (p1x - p2x) + (p2y - p1y) * 2) / divisor;

 float b = (2 * (p2x * p2x * tp1 - p1x * p1x * tp2) - p1x * p1x * tp1 + p2x * p2x * tp2 + p1x * 
 p2x * (tp2 - tp1) + 3 * (p1x + p2x) * (p1y - p2y)) / divisor;

 float c = (p1x * p1x * p1x * tp2 - p2x * p2x * p2x * tp1 + p1x * p2x * (p1x * (2 * tp1 + tp2) - 
 p2x * (tp1 + 2 * tp2)) + 6 * p1x * p2x * (p2y - p1y)) / divisor;

 float d = ((p1x * p2x * p2x - p1x * p1x * p2x) * (p2x * tp1 + p1x * tp2) - p1y * p2x * p2x * 
 p2x + p1x * p1x * p1x * p2y + 3 * p1x * p2x * (p2x * p1y - p1x * p2y)) / divisor;


I've double checked this and it should give the same results as the equations you supplied.

avatar image
0

Answer by Aru3 · Aug 26, 2017 at 05:59 AM

AnimationCurve is a simple spline of cubic equations, where for each segment you specify the (time, value) coordinates and slope for each of two end points (the first point's "out" "tangent", second one's "in"). A cubic equation is the simplest polynomial which can meet these criteria.

This is also known as a cubic Hermite spline, where the only difference is that AnimationCurve allows you to assign different slopes for each direction from a keyframe (a point), which creates discontinuities in the first derivative (sharp angles). However, this does not change the formula.

https://en.wikipedia.org/wiki/Cubic_Hermite_spline

It took me some time (much more than I'd like to admit...) but I simplified the system of cubic equations for the endpoints into this form.

 pd = 1/(p2x-p1x)
 td = t-p1x
 ta = td*pd
 
 out(t) = (((p2s+p1s)/2 - (p2y-p1y)*pd)*ta*(t*2 + p1x - p2x*3) + (p2s-p1s)/2*(t + p1x - p2x*2))*ta + p2s*td + p1y

Isolated t to calculate coefficients in advance, providing a fast t evaluation:

 pd = 1/(p2x-p1x)
 td = pd*(p2s-p1s)
 a = pd^2*(p2s + p1s - 2*pd*(p2y-p1y))
 
 b = (-a*3*(p2x + p1x) + td)/2
 c = p2x*(a*3*p1x + -td) + p2s
 d = p1x*(a/2*p1x*(-p2x*3 + p1x) + td*(p2x + -p1x/2) + -p2s) + p1y
 
 out(t) = t*(t^2*a + t*b + c) + d

I had the same question, was looking for a straightforward answer. Because my search query took me here and this is the closest I could find, I assume such solutions to this exact problem are not abundant, so I thought I'd share mine. I derived it because I need to emulate the same function outside of unity. Looking at the other three answers here, they seem to be correct but not simplified (trust me this is not an easy task) (Varaughe's leaves out the evaluation of the Bezier curve he made from the AnimationCurve, as it is a well-known thing).

I tested these against AnimationCurve for correctness with a Python script which can randomize all six parameters of the cubic function:

 # isolated t
 def curve1(t,p1x,p2x,p1y,p2y,p1s,p2s):
     e = 1/(p2x-p1x)
     f = e*(p1s-p2s)
     a = (p1s + p2s + 2*e*(p1y-p2y))*e**2
     b = (a*3*(p2x+p1x) + f)/-2
     c = p2x*(a*3*p1x + f) + p2s
     d = p1x/2*(a*p1x*(p1x - p2x*3) + f*(p1x - p2x*2) - p2s*2) + p1y
     return t*(t**2*a + t*b + c) + d
 
 # short form
 def curve2(t,p1x,p2x,p1y,p2y,p1s,p2s):
     pd = 1/(p2x-p1x)
     td = t-p1x
     ta = td*pd
     return ((t*2 + p1x - p2x*3)*((p2s+p1s)/2 - (p2y-p1y)*pd)*ta + (t + p1x - p2x*2)*(p2s-p1s)/2)*ta + p2s*td + p1y
 
 # Paulius
 def curve_Paulius(t,p1x,p2x,p1y,p2y,p1s,p2s):
     xd = p2x-p1x
     t = (t-p1x)/xd
     return (2*t**3 - 3*t**2 + 1)*p1y + (t**3 - 2*t**2 + t)*p1s*xd + (t**3 - t**2)*p2s*xd + (-2*t**3 + 3*t**2)*p2y
 
 def test(curve, times, curve_parameters):
     out = []
     for i in times:
         out.append(curve(i, *curve_parameters))
     return out
 
 from random import random
 rand_args = []
 for i in range(4):
     rand_args.append(random()*100)
 for i in range(2):
     rand_args.append(random()*2)
 
 rand_times = []
 e,f = rand_args[0:2]
 points = 21
 # interval count is points - 1
 for i in range(points - 1):
     td = (f - e)/(points - 1)
     rand_times.append(random()*td + e + i*td)
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Varaughe · Dec 03, 2017 at 06:41 PM 0
Share

you should check runtime curve editor ,there the math behind AnimationCurve is accurately replicated, I don't understand what do you mean by is not correct or outdated , did the Unity $$anonymous$$m changed the equation by which the bezier(or hermite) curves are plotted ? I don't see any need for doing that ...

avatar image Aru3 · Apr 19, 2018 at 02:55 PM 0
Share

Your post confused me. I looked at it again, and I understand it now, I apologize, it is correct, I will edit my post. You describe turning an AnimationCurve into a cubic Bezier curve, by calculating control point values like so:

dx3 = (p2x-p1x)/3

c1y = p1y + dx3*p1s

c2y = p2y - dx3*p2s

Then the AnimationCurve can be evaluated as the y portion of said Bezier curve, via this formula which I fetched from wikipedia:

y(t) = (1-t)^3*p1y + 3*(1-t)^2*c1y + 3*(1-t)*t^2*c2y + t^3*p2y

While my post ins$$anonymous$$d calculates the coefficients of the cubic polynomial, for slightly faster evaluation of the curve at t.

Paulius's is also correct, I previously forgot to normalize t:

t = (t - p1x)/(p2x - p1x)

avatar image
0

Answer by eocron · 4 days ago

Here is my implementation for ones who want to port it to other languages or shaders. Inludes all wrapping, exact point values and based on some of the answers here of whats happening in between points:

 public class AnimationCurveDto
 {
     public KeyDto[] Ranges;
     public WrapMode PreWrap;
     public WrapMode PostWrap;

     public struct KeyDto
     {
         public float a;
         public float b;
         public float c;
         public float d;
         public Vector2 t;
         public Vector2 v;
     }
     public AnimationCurveDto(AnimationCurve curve)
     {
         Ranges = new KeyDto[curve.keys.Length - 1];
         for(int i = 0; i < curve.keys.Length-1; i++)
         {
             Ranges[i] = Create(curve.keys[i], curve.keys[i + 1]);
         }
         PreWrap = curve.preWrapMode;
         PostWrap = curve.postWrapMode;
     }

     public float Evaluate(float t)
     {
         var l = Ranges[0];
         var r = Ranges[Ranges.Length - 1];

         if(l.t.x > t)
         {
             if(PreWrap == WrapMode.Clamp || PreWrap == WrapMode.ClampForever)
             {
                 return l.v.x;
             }
             t = Wrap(t, PreWrap, l, r);
         }
         if(r.t.y <= t)
         {
             if (PostWrap == WrapMode.Clamp || PostWrap == WrapMode.ClampForever)
             {
                 return r.v.y;
             }
             t = Wrap(t, PostWrap, l, r);
         }

         for (int i = 0; i < Ranges.Length; i++)
         {
             var o = Ranges[i];
             if(o.t.x <= t && o.t.y > t)
             {
                 return o.a * Mathf.Pow(t,3) + o.b * Mathf.Pow(t,2) + o.c * t + o.d;
             }

         }
         if (r.t.y == t)
         {
             return r.v.y;
         }
         return 0;
     }

     private static float Wrap(float t, WrapMode mode, KeyDto a, KeyDto b)
     {
         if (mode == WrapMode.PingPong)
         {
             t = a.t.x + Mathf.PingPong(t - a.t.x, b.t.y - a.t.x);
         }
         else if (mode == WrapMode.Loop)
         {
             t = a.t.x + Mathf.Repeat(t - a.t.x, b.t.y - a.t.x);
         }
         return t;
     }

     private static KeyDto Create(Keyframe p1, Keyframe p2)
     {
         float p1x = p1.time;
         float p1y = p1.value;
         float tp1 = p1.outTangent;
         float p2x = p2.time;
         float p2y = p2.value;
         float tp2 = p2.inTangent;

         var result = new KeyDto();
         result.t = new Vector2(p1.time, p2.time);
         result.v = new Vector2(p1.value, p2.value);
         if (tp1 == float.PositiveInfinity || tp1 == float.NegativeInfinity || tp2 == float.PositiveInfinity || tp2 == float.NegativeInfinity)
         {
             if (tp1 == float.NegativeInfinity && tp2 == float.NegativeInfinity ||
                 tp1 == float.NegativeInfinity && IsSimple(tp2) ||
                 tp2 == float.NegativeInfinity && IsSimple(tp1))
             {
                 result.d = p2.value;
             }
             else
             {
                 result.d = p1.value;
             }
         }
         else
         {
             var divisor = (p1x * p1x * p1x) - (p2x * p2x * p2x) + (3 * p1x * p2x * (p2x - p1x));
             result.a = ((tp1 + tp2) * (p1x - p2x) + (p2y - p1y) * 2) / divisor;
             result.b = (2 * (p2x * p2x * tp1 - p1x * p1x * tp2) - p1x * p1x * tp1 + p2x * p2x * tp2 + p1x * p2x * (tp2 - tp1) + 3 * (p1x + p2x) * (p1y - p2y)) / divisor;
             result.c = (p1x * p1x * p1x * tp2 - p2x * p2x * p2x * tp1 + p1x * p2x * (p1x * (2 * tp1 + tp2) - p2x * (tp1 + 2 * tp2)) + 6 * p1x * p2x * (p2y - p1y)) / divisor;
             result.d = ((p1x * p2x * p2x - p1x * p1x * p2x) * (p2x * tp1 + p1x * tp2) - p1y * p2x * p2x * p2x + p1x * p1x * p1x * p2y + 3 * p1x * p2x * (p2x * p1y - p1x * p2y)) / divisor;
         }

         return result;
     }

     private static bool IsSimple(float t)
     {
         return t != float.NegativeInfinity && t != float.PositiveInfinity;
     }
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

25 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Extending tangents in Animation window 0 Answers

Tangent for 5th order Bezier curve 2 Answers

Baked Animation VS Bezier Tween 0 Answers

Mecanim ik curve 0 Answers

Find Vector3 point exactly between two gameobjects with an offset perpendicular to the line connecting the two gameobjects 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges