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?
It uses Bezier Curves, like it should. If you want to evaluate those, you can do a quick google search :)
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
Answer by Varaughe
Aug 06, 2013 at 03:21 AM
Alright ,so empiricaly I found something that matches exactly the animation curve drawn by unity ... it can be drawn as a bezier curve ... as you know the AnimationCurve of Unity , has .time and .value for the two keyframes of the segment(lets call the two endpoints P1,P2, time is x and value is y coordinate), and a out tangent(first point) and in tangent(2nd point) , can be called tgOut and tgIn. The Bezier curve (the cubic one),its equation is well known,can be found on wiki, has aside the 2 end points(P1,P2), 2 control points ... let's call them C1 , C2 . We have to corelate C1,C2 with tgOut and tgIn ,this relation is not given by unity,and I found it empiricaly:
float tangLengthX = Mathf.Abs(p1.x-p2.x)*0.333333f;
float tangLengthY = tangLengthX ;
c1 = p1;
c2 = p2;
c1.x += tangLengthX ;
c1.y += tangLengthY * tgOut;
c2.x -= tangLengthX ;
c2.y -= tangLengthY * tgIn;
//draw now the bezier using p1,c1,c2,p2
remember that tgOut and tgIn need a scaling , to match the ratio of the window's width and height where they are going to be drawn ,and the ratio of gradations of which scope the curve's time and value are part ...
to be more explicit ..... let's say that **gridRect** is the rect in pixels where the curve is to be drawn and **gradRect** gives the min and max values for the gradations of the grid(e.g. the time ranges from 0 to 5, and the values from 0 to 7 ...so gradation maximum is 7 for y axis and 5 for x axis) ....
so: let's say
ratio = (gridRect.height/gridRect.width)(gradRect.width/gradRect.height) then tgOut is ratio*curve[i].outTangent and tgIn* is ratio*curve[i+1].inTangent (where curve is of type AnimationCurve)
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;
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
t is from 0 to 1 in this case, i.e. t = Mathf.InverseLerp(keyframe0.time, keyframe1.time, time)
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).
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)
Answer by SuperPingu
3 days ago
Unity define a curve with 2 keyframes, each composed of a point and a tangeant. I guess the simplest curve matching that is a third degree polynom. Given the 2 points and tangeants, it is possible to compute the polynom 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 have not checked that this is what Unity is doing but it worth a try I guess.
Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.
The best place to ask and answer questions about development with Unity.
To help users navigate the site we have posted a user guide.
If you are a new user, check out our FAQ for more information.
If you are a moderator, see our Moderator Guidelines page.
We are making improvements to UA, see the list of changes.
For troubleshooting common problems with Unity 5.x Editor (including Win 10).
Answers and Comments
18 People are following this question.
Extending tangents in Animation window
Float variable not even updating?
Can I make animations snap to a frame?
Bezier movement is erratic
Tranform Animation Curve ruins Gravity