I’m hoping to use Unity for a neuroscience experiment, for which we need very reliable timestamps of event onsets (i.e. when a certain stimulus appears on the monitor or changes). By “reliable” I mean with less than 1 ms jitter, preferably much less.
The standard way this is done is by timing the sending of event codes to the onset of the monitor’s vertical blank period. In Unity, there is the WaitForEndOfFrame() class, which is called after all the rest of the processing for the frame has been finished, and I was hoping to use this.
However what I’m wondering is what triggers WaitForEndOfFrame to be active. Is it simply that it happens after all the rest of the processing for the frame has been finished? In this case, it would occur later on frames with more processing, meaning that it would have a large amount of jitter relative to actual frame onset from frame to frame, rendering it fairly useless for us. Alternatively, does it actually get triggered by the vertical blank signal from the monitor? In which case, it is perfect for our needs.
Anything that sheds light on this would be appreciated.
I’m trying to do the same thing and have been experimenting with an arduino, a photodiode and an oscilloscope. The results so far are not encouraging. It appears that with vsync enabled there is definitely correlation between the timing of frames in Unity and when the frames get displayed on the monitor. Unity is obviously accessing the vblank signal at some point. As long as things are running smoothly and Unity is keeping up with the frame rate the delay between Unity timing and display timing is consistent. As soon as something disrupts this timing it will take a few frames for Unity to catch up again, but it does recover.
Also, there is some buffering of frames, probably by the video card. Unfortunately the number of buffered frames can change over time causing discreet jumps in the delay time equal to the frame rate. In my case I’m using a Dell S2417DG monitor running at 165Hz. The delay time is usually solid around 16ms but when an additional frame is buffered the delay is ~22ms. Running at 60Hz the delay varies from 50-67ms.
Without accessing the vblank signal directly I currently don’t see how to get more accurate timing information.
WaitForEndOfFrame happens after everything in the frame has been completed: cpu-side camera rendering; animators; post-late-update stuff; your scripts; even the editor overhead.
Below is a profiler timeline showing location of coroutines that yield for a new WaitForEndOfFrame.