- Home /
How should scripts cache a function result each frame?
I'm looking for a good way to cache an expensive function's result each frame. This code looks like it will work, but it's a bit complicated and requires deriving from MonoBehavior.
It seems like this would be needed often with Unity, since update order is unknown. Is there a better way to do it?
using UnityEngine; using System.Collections;
public class MyClass : MonoBehaviour { bool enableLateLateUpdate = true; static bool myVarCachedThisFrame = false; static float myVar;
void Start() {
StartCoroutine(LateLateUpdate());
}
public static float MyVar {
get {
if (myVarCachedThisFrame) return myVar;
//some expensive calculation:
myVar = Mathf.Sqrt(Mathf.Sqrt(Mathf.Sqrt(myVar)));
myVarCachedThisFrame = true;
return myVar;
}
}
IEnumerator LateLateUpdate() {//Coroutines update after LateUpdate. I think.
while (enableLateLateUpdate) {
MyClass.myVarCachedThisFrame = false;
yield return 0;//wait one frame
}
}
}
Answer by duck · May 09, 2010 at 09:51 AM
You could simplify this by using Time.frameCount.
Simply check whether the frame count has increased since last time you calculated the expensive value.
Eg:
public static float MyVar { get { if (lastCalculatedFrame == Time.frameCount) {
// return cached value
return myVar;
} else {
// some expensive calculation:
myVar = Mathf.Sqrt(Mathf.Sqrt(Mathf.Sqrt(myVar)));
lastCalculatedFrame = Time.frameCount;
return myVar;
}
}
}
This removes the need for a coroutine at all, and puts the responsibility of when to recalculate within the property code itself.
That's better. Thanks!
Also, it looks like I may have been wrong about coroutines updating after late update. The last post on this question shows them updating between update and lateupdate: http://answers.unity3d.com/questions/1405/is-function-update-short-for-function-start-whiletrue
http://www.unifycommunity.com/wiki/index.php?title=Event_Execution_Order
read this - it gives information about the order each type of event (including coroutines) is called in
Thanks. So the way I posted above would work as intended if the LateLateUpdate coroutine yielded on WaitForEndOfFrame.