- Home /
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");
}
}
OnGUI will never 'remember' what you printed in previous frames. You need to keep that in a separate data structure, which you then convert into label prints in OnGUI.
Yep, I do. Take a second look at the script in case you missed it. But the container I use is cleared out in OnGUI. I tried clearing it in Update, but the final call to OnGUI is called after update and after LateUpdate. So, I can't figure out where in the frame to clear my container.
Oh I see. You definitely shouldn't be clearing it in OnGUI. You won't even see it once if you do that!
Answer by Bunny83 · Oct 31, 2011 at 03:59 AM
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.
You can also set $$anonymous$$onoBehaviour.useGUILayout to false to disable the Layout event, but you can't use GUILayout or GUI.Window in this case. I guess using GUILayout would even be simpler so you don't have to struggle with Rects. GUILayout will arrange everything automatically ;)
Just have a look into GUILayout
Your answer
Follow this Question
Related Questions
Can't draw GUI.Label text on subpixel values 0 Answers
Default text / Already written text on GUI Text Field. 1 Answer
GUI.Label question about Resolution 1 Answer
show entered amount gui/label 2 Answers