You need this ALL THE TIME when developing, and Unity lacks it as a core feature:
- Create a Text label on your GUI
- Drag/drop a variable onto the label, and it will automatically display the value
Completely impossible, due to short-sighted design decisions in the Unity Editor from 10 years ago that never got changed. So, let’s fix it. It’s hugely annoying not being able to do this!
Approach
Using Reflection, we’ll look at the target object, find the list of all properties and fields, and find the one with the desired name, and display it.
Source
Here’s the original source; but if you want to improve it, click here for a Gist you can fork, comment on, etc
[csharp]
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Reflection;
/**
License: do whatever you want.
Author: @t_machine_org
*/
public class DisplayVariable : MonoBehaviour
{
/** 1/2: Drag/drop a gameobject that has a var you want to display… */
public GameObject target;
/** 2/2: Type the name of the variable that you want to display… */
public string variableName;
/** Don’t refresh at 60FPS; wasteful! */
private float updateNSeconds = 0.25f;
private float lastUpdateTime = 0f;
// Update is called once per frame
void Update ()
{
lastUpdateTime += Time.deltaTime;
/** Don’t refresh at 60FPS; wasteful! */
if (lastUpdateTime > updateNSeconds) {
lastUpdateTime = 0;
Text myText = GetComponent<Text> ();
if (myText == null) {
Debug.LogError ("Missing Text object, please disable this DisplayVariable component");
} else if (variableName == null || target == null) {
myText.text = "[Unattached]";
} else {
bool foundIt = false;
string valueAsString = "";
foreach (Component subComponent in target.GetComponents ( typeof(Component))) {
FieldInfo[] fields = subComponent.GetType ().GetFields ();
foreach (FieldInfo fieldInfo in fields) {
//Debug.Log("Obj: " + subComponent.name + ", Field: " + fieldInfo.Name);
if (fieldInfo.Name.Equals (variableName)) {
valueAsString = fieldInfo.GetValue (subComponent).ToString ();
foundIt = true;
break;
}
if (foundIt)
break;
}
if (! foundIt) {
PropertyInfo[] properties = subComponent.GetType ().GetProperties ();
foreach (PropertyInfo propertyInfo in properties) {
//Debug.Log ("Obj: " + subComponent.name + ", Property: " + propertyInfo.Name);
if (propertyInfo.Name.Equals (variableName)) {
valueAsString = propertyInfo .GetValue (subComponent, null).ToString ();
foundIt = true;
break;
}
if (foundIt)
break;
}
}
}
/** set the text */
myText.text = variableName+" = "+valueAsString;
}
}
}
}
[/csharp]
Usage
- Add this script to any GameObject that has a Text component (e.g. create from menu “UI – Text”)
- Drag/drop the object you want to debug onto the “Target” field
- Type the C# source-code name of the variable/field you want to debug into “Variable Name” field
…and it will update (by default: 4FPS. Tweak as needed)
Improvements
- It would be much much cooler to have a drop-down menu for the variable name.
- It would be neater to save the FieldInfo stuff at Editor time / startup, and stop using Reflection multiple times per frame.
- But this is a debug tool, so frankly: neither of those are essential.
5 replies on “Unity3D: display a variable instantly on screen”
Adding my 0.02$ :
1. You can place a [RequireComponent(typeof(Text))] at the class level, to require that this component will be used ONLY on objects that also have a Text component.
2. Is there a real need to lookup the property name inside Update() ? sounds like this could be done in Awake or Start.
Both sound good. Fork the gist!
NB: there is huge value in doin this in update, though. Unity has TERRIBLE handling of listening to changes on variables (because it breaks C# built-ins for this, IIRC – side-effect of unity serialization. But might be C# itself that’s the problem?)
So … if you changed the variable while you were running, e.g. paused … any setup done in awake won’t get run. But if you’pre rechecking in Update, it all Just Works.
Unity does support this through a little known Inspector config.
If the (member) variable/property is referenced by a MonoBehaviour, you can change the Inspector to Debug (through the tab pane settings to the right of the Inspector tab).
*Very* useful.
That’s really not the same – its nowhere near as useful!
Try this: you simultaneously view exactly the data you want, all on screen, in game, while testing :).