想使用Animation曲线制作变速移动, 需要 当前曲线下面积/曲线总面积 获取当前移动进度,在网上找到了unity animationCurve的实现代码,修改后做积分可以求得面积代码如下:
public float AreaUnderCurve(AnimationCurve curve, float w, float h)
{
var areaUnderCurve = 0f;
var keys = curve.keys;
for (var i = 0; i < keys.Length - 1; i++)
{
// Calculate the 4 cubic Bezier control points from Unity AnimationCurve (a hermite cubic spline)
var K1 = keys[i];
var K2 = keys[i + 1];
var A = new Vector2(K1.time * w, K1.value * h);
var D = new Vector2(K2.time * w, K2.value * h);
var e = (D.x - A.x) / 3.0f;
var f = h / w;
var B = A + new Vector2(e, e * f * K1.outTangent);
var C = D + new Vector2(-e, -e * f * K2.inTangent);
/*
* The cubic Bezier curve function looks like this:
*
* f(x) = A(1 - x)^3 + 3B(1 - x)^2 x + 3C(1 - x) x^2 + Dx^3
*
* Where A, B, C and D are the control points and,
* for the purpose of evaluating an instance of the Bezier curve,
* are constants.
*
* Multiplying everything out and collecting terms yields the expanded polynomial form:
* f(x) = (-A + 3B -3C + D)x^3 + (3A - 6B + 3C)x^2 + (-3A + 3B)x + A
*
* If we say:
* a = -A + 3B - 3C + D
* b = 3A - 6B + 3C
* c = -3A + 3B
* d = A
*
* Then we have the expanded polynomal:
* f(x) = ax^3 + bx^2 + cx + d
*
* Whos indefinite integral is:
* a/4 x^4 + b/3 x^3 + c/2 x^2 + dx + E
* Where E is a new constant introduced by integration.
*
* The indefinite integral of the quadratic Bezier curve is:
* (-A + 3B - 3C + D)/4 x^4 + (A - 2B + C) x^3 + 3/2 (B - A) x^2 + Ax + E
*/
float a, b, c, d;
a = -A.y + 3.0f * B.y - 3.0f * C.y + D.y;
b = 3.0f * A.y - 6.0f * B.y + 3.0f * C.y;
c = -3.0f * A.y + 3.0f * B.y;
d = A.y;
/*
* a, b, c, d, now contain the y component from the Bezier contorl points.
* In other words - the AnimationCurve Keyframe value * h data!
*
* What about the x component for the Bezier control points - the AnimationCurve
* time data? We will need to evaluate the x component when time = 1.
* because we use curve range 0 - 1
*
* x^4, x^3, X^2, X all equal 1, so we can conveniently drop this coeffiecient.
*
* Lastly, for each segment on the AnimationCurve we get the time difference of the
* Keyframes and multiply by w.
*
* Iterate through the segments and add up all the areas for
* the total area under the AnimationCurve!
*/
var t = (K2.time - K1.time) * w;
var area = ((a / 4.0f) + (b / 3.0f) + (c / 2.0f) + d) * t;
areaUnderCurve += area;
}
return areaUnderCurve;
}