OnGUI called after LateUpdate screwing up debug text database

Hey all,
I’m trying to make a debug text database to output basic info to the screen. I’m a complete Unity newb and I can’t figure out an effective way to accomplish my goal. But I’m betting someone out there knows a better unity specific way of accomplishing this.

What I’d like is to output a series of debugging text (things like player position, camera position, etc) to the screen. So, in previous game engines you just output the text at the end of your update loop. Generally, I just make a container that you fill up through your update cycle with a series of debugging statements, and then when the container starts printing to the screen, it auto-positions the text for me. And, after printing, I delete the string. I delete it to achieve an immediate mode effect, and don’t fill up my container with multiple copies of the same string.

But in unity, it seems like I can only print to the screen during OnGUI, which is called several times a frame. So, when I clear out my text container after printing once, it will still be called again, but there’s nothing left to print. It already printed earlier in the same frame.

How do I achieve this effect in Unity the proper way?

Here’s the script I use to achieve this effect currently

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class LevelUpdate : MonoBehaviour {

	public float LabelHeight = 22.0f;
	public float LabelWidth  = 400.0f;
	
	public System.Collections.Generic.List<string> ScreenText = new System.Collections.Generic.List<string>();
	private GameObject Player = null;
	
	// Use this for initialization
	void Start ()
	{
		Player = GameObject.Find("Player");
	}
	
	// Update is called once per frame
	void Update () 
	{
		ScreenText.Add( "Player Position:" + Player.transform.localPosition.ToString());	
	}
	
	void LateUpdate()
	{
	}
	
	void OnGUI()
	{
		float CurrentScreenTextPos = 0.0f;
		int count = 0;
		foreach( string screentext in ScreenText )
		{
			if( ( screentext != null ) && ( screentext != "" ) )
			{
				Rect label = new Rect( 0.0f, CurrentScreenTextPos, LabelWidth, LabelHeight );
				GUI.Label( label, screentext);
				CurrentScreenTextPos += LabelHeight;
				count++;
			}
		}
		ScreenText.Clear();
		GUI.Label( new Rect(0.0f, CurrentScreenTextPos, LabelWidth, LabelHeight), "I printed out " + count.ToString() + " lines");
	}	
}

Everything is fine except one little thing. OnGUI is called multiple times in one frame, but with a different Event! OnGUI will only draw your stuff one time in a frame. That confuses a lot people because the name OnGUI is not a good choice. It should be something like OnGUIEvent. The Event class specifies why OnGUI is called and may hold additional information (like for key or mouse events).

Usually OnGUI is called two times each frame, all other events are related to some user input events. EventType.Layout is always called first so Unity can collect all elements you want to draw and create the layout (if you use GUILayout). EventType.Repaint is called after the layout step and this event will actually draw the elements and handle the input. If you want to clear your list, check for the right event:

if (Event.current.type == EventType.Repaint)

Another little sidenote: the layout and repaint iteration have to perform the same GUI calls (for the same frame) or the layouting will fail. If you change the condition of a conditional drawn GUI element in the layout step, Unity will throw an error that the layout-stack size is wrong.