Unity3D offers many per-frame callbacks, the most used being Update
. There are also lesser-used ones like OnWillRenderObject
, OnRenderObject
, and OnPostRender
. With respect to the order in which these callbacks are called, when is Time.frameCount
incremented?
I'm trying to synchronize frame-grabs I'm capturing after rendering completes with object properties recorded from other callbacks in that frame. I found that when OnPostRender
is called, Time.frameCount
has already been incremented, so that the frame I'm being notified of is actually the previous frame. For this reason, I'd like to know what other callbacks are called after the frame count has been incremented.
I wrote this script in order to capture when Time.frameCount
is changed:
using UnityEngine;
public class OnFrameCounterDetector : MonoBehaviour {
int frameNumber = 0;
string prevMethod;
private void Awake() {
Time.fixedDeltaTime = 1 / 60;
prevMethod = System.Reflection.MethodBase.GetCurrentMethod().Name;
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnEnable() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void Start () {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void FixedUpdate() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void Update () {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void LateUpdate() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnWillRenderObject() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnPreCull() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnBecameVisible() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnBecameInvisible() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnPreRender() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnRenderObject() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnPostRender() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnRenderImage(RenderTexture source, RenderTexture destination) {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnDrawGizmos() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnGUI() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnApplicationPause(bool pause) {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void OnDisable() {
CheckFrameCount(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private void CheckFrameCount(string callback) {
if (Time.frameCount > frameNumber) {
Debug.LogFormat("frameCount changed between {0} and {1}", prevMethod, callback);
frameNumber = Time.frameCount;
}
prevMethod = callback;
}
}
Inside the editor, I got the change between OnGUI
OR OnRenderObject
and FixedUpdate
, but the scene was almost empty, with just a single camera and a game object with a Sprite Renderer
on it.
The difference was if I had the game object selected or the camera in the hierarchy, if the GO was selected, then OnRenderObject
would be signaled, if not (i.e.: keep the camera selected in hierarchy), OnGUI
.
You may use this script in more detailed scenes, since most of the callbacks aren't called at all in a simple scene, curious at the results.
BTW, I didn't bother to add coroutines with the various yields, they could be added though very easily to catch more "moments" in the game loop, like the one between Update and LateUpdate, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With