This BlobCurve runs about 12 times faster than UnityEngine.AnimationCurve. And about 30% faster than Unity.Animation.AnimationCurve.
Basically, it uses only one dot(float4,float4) for one sample.
public float Sample(float time)
{
TimeCheck();
float t = (time - StartTime) * InvDuration;
float tSq = t * t;
float4 timeSerial = float4(tSq * t, tSq, t, 1);
return dot(Factors, timeSerial);
}
Because Matrix multiplication is done in blob baking.
/// <summary>
/// Convert From Cubic Hermite spline parameter
/// </summary>
public NativeCurveSegment(
float value0, float tangent0, float time0,
float value1, float tangent1, float time1)
{
float duration = time1 - time0;
float4 factors = mul(S_BezierMat, float4(value0, value0 + (tangent0 * duration * OneThird), value1 - (tangent1 * duration * OneThird), value1));
this = new NativeCurveSegment(factors, time0, duration);
}
So it should run much faster than Unity.Animation.Curves.
keyframe index search is done by a cached local first binary search.
Source attached.
This curve has been used in my game for some time. It does reference several functions from my Toolkit, but that’s trivial. Will upload to GitHub when the whole lib is ready. Let me know if there are optimization suggestions.
Test Code
[NaughtyAttributes.Button(nameof(PerformanceTest))]
unsafe private void PerformanceTest()
{
if (curve == null || !blobCurveRef.IsCreated) return;
var keys = curve.keys;
var start = curve.keys[0].time;
var time = start;
var watch = System.Diagnostics.Stopwatch.StartNew();
//-------------------------------------------------------------------------------------------------
var pFun = NativeDelegate<EvaluateCall>.Compile(BurstEvaluateBlobCurve).AsFunctionPointer().Invoke;
var copy = blobCurveRef;
var value = 0f;
watch.Restart();
pFun(start, performanceTestStepLen, sampleCount, UnsafeUtility.AddressOf(ref copy), &value);
watch.Stop();
var tick = watch.ElapsedTicks;
//-------------------------------------------------------------------------------------------------
var copy2 = unityCurve;
var pFunUnity = NativeDelegate<EvaluateCall>.Compile(BurstEvaluateUnityCurveBlob).AsFunctionPointer().Invoke;
var value1 = 0f;
watch.Restart();
pFunUnity(start, performanceTestStepLen, sampleCount, UnsafeUtility.AddressOf(ref copy2), &value1);
watch.Stop();
var tick1 = watch.ElapsedTicks;
//-------------------------------------------------------------------------------------------------
watch.Restart();
var value2 = 0f;
for (int i = 0; i < sampleCount; i++)
{
value2 += curve.Evaluate(time);
time += performanceTestStepLen;
}
watch.Stop();
var tick2 = watch.ElapsedTicks;
float f = System.Diagnostics.Stopwatch.Frequency * 1.0e-3f;
float ms = tick / f;
float ms1 = tick1 / f;
float ms2 = tick2 / f;
Debug.Log($"Simpled {sampleCount} times, BlobCurve : {tick} ticks {ms} ms, Unity.Animation.AnimationCurve : {tick1} ticks {ms1} ms, UnityEngine.AnimationCurve : {tick2} ticks {ms2} ms");
//Debug.Log($"None-Bursted BlobCurve used{tick2} ticks {ms2} ms");
}
unsafe delegate void EvaluateCall(float time, float step, int count, void* ptr, float* valueOut);
[BurstCompile]
unsafe public static void BurstEvaluateBlobCurve(float time, float step, int count, void* pBlobCurveRef, float* valueOut)
{
var assetReference = UnsafeUtility.AsRef<BlobAssetReference<BlobCurve>>(pBlobCurveRef);
ref var blobCurve = ref assetReference.Value;
var value = 0f;
var cache = BlobCurveCache.Empty;
for (int i = 0; i < count; i++)
{
value += blobCurve.EvaluateIgnoreWrapMode(time, ref cache);
time += step;
}
*valueOut = value;
}
[BurstCompile]
unsafe public static void BurstEvaluateUnityCurveBlob(float time, float step, int count, void* pAnimCurve, float* valueOut)
{
ref var curve = ref UnsafeUtility.AsRef<UnityCurve>(pAnimCurve);
var value = 0f;
for (int i = 0; i < count; i++)
{
value += AnimationCurveEvaluator.Evaluate(time, ref curve);
time += step;
}
*valueOut = value;
}
Also, I got float2 float3 curve working.
the reason for them is that keyframe searching is the slowest part of curve evaluation. keep xyz synced in one curve is much faster than using 3 curves.
Quaternion curve and Transform curve is under test. will upload later.
6404436–716880–BlobCurve.cs (26.2 KB)
6404436–716883–BlobCurve2.cs (17 KB)
6404436–716886–BlobCurve3.cs (18.2 KB)