OnGUI called after WaitForEndOfFrame on mouseDown events

When running this code:

public class TestScript : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
		Debug.Log("----------------beginning of frame");
		StartCoroutine("EndOfFrame");
	}

	private void OnGUI()
	{
		Debug.Log("------------OnGui" + Event.current.type);
	}

	IEnumerator EndOfFrame()
	{
		yield return new WaitForEndOfFrame();
		Debug.Log("----------------end of frame");
	}
}

We get this output:

----------------beginning of frame
------------OnGuiLayout
------------OnGuiRepaint
----------------end of frame
----------------beginning of frame
------------OnGuiLayout
------------OnGuiRepaint
----------------end of frame
------------OnGuiLayout
------------OnGuimouseDown
----------------beginning of frame
------------OnGuiLayout
------------OnGuiRepaint
----------------end of frame

To our knowledge, the “endOfFrame” text should happen after the “OnGuimouseDown” text but before the “beginning of frame” text, but instead it always appears after the “OnGuiRepaint” text. Is there something we are doing wrong with the yield WaitForEndOfFrame coroutine? It happens in a built engine and in the editor.

You interpreted the result wrong. It’s not called after the end of the current frame, but at the beginning of the next frame. The input processing happens before Update. Try printing Time.frameCount with each of your Debug.Logs to see to which frame the log belongs. See the event order. The diagram isn’t complete but it should give a better overview. Note that the point “GUI rendering” really only includes the actual repaint event, not the input processing which is done at the beginning of the frame.

There is no reliable callback that is always called at the very beginning of a frame. The best option is to do frame initialization things at the very end of your “WaitForEndOfFrame” coroutine.

An alternative is to do initialization in a seperate method which you call before anything else in any of your functions. The method only executes it’s body if the current frame count is greater than the last saved frame count.

int lastFrame = -1;

void Init()
{
    if (Time.frameCount > lastFrame)
    {
        lastFrame = Time.frameCount;
        // Do your frame initialization here.
    }
}

You can savely call Init as often as you want before you do anything else. This method will only execute once per frame due to the frame count check.