Custom real-time DEBUG window (C# scripts)

Hi to everyone !!!
I’m the one that create the post “C# destructor question” with Alexo’s account because I was not able to register to the forum.
I’ve decided to post the code I did to make a real-time Debug window in your project that could be useful to show the variables values for not-attacched-to-gameobjects script (you cannot see these value in the inspector debug view).

First of all we need a simple structure to store the informations we need:

public class DebugData {

   private string dataName; // the label to show in DEBUG window
   private string dataValue; // the value to show in DEBUG window

   public DebugData (string dataName) {
      this.dataName = dataName;
      this.dataValue = "miss";
   } // constructor (string)

   public DebugData (string dataName, string dataValue) {
      this.dataName = dataName;
      this.dataValue = dataValue;
   } // constructor (string, string)
	
   public string getDataName () {
      return dataName;
   } // getDataName
	
   public string getDataValue () {
      return dataValue;
   } // getDataValue
	
   public void setDataName (string dataName) {
      this.dataName = dataName;
   } // setDataName
	
   public void setDataValue (string dataValue) {
      this.dataValue = dataValue;
   } // setDataValue

} // DebugData

Now we need a static (so we don’t need instances for this) class accessible to all classes of the project:

using System;
using System.Collections;

public static class DebugManager {
	
   public static bool DEBUG_ENABLED = true; // the boolean value for DEBUG MODE
	
   private static ArrayList list = new ArrayList (); // the variables collection to display in the DEBUG window

   public static DebugData createDebugData (string label) {
      // create the new instance of DEBUG DATA with default value
      DebugData inst = new DebugData (label);
      // add the new object in the container
      list.Add (inst);
      // return the reference to the new object
      return inst;
   } // createDebugData

   public static void removeDebugData (DebugData item) {
      list.Remove (item);
   } // removeDebugData (DebugData)
	
   public static void clearItems () {
      list.Clear ();
   } // clearItems
	
   public static ArrayList getItems () {
      return list;
   } // getItem

} // DebugManager

At last we need to create a little window to make possible to show the informations in realtime:

using UnityEngine;
using System.Collections;

public class DebugGUI : MonoBehaviour {
	
   // START ---> FPS calculation usefull variables
      public float updateInterval = 0.5f; // the time must pass to cache the frames value
      private double lastInterval; // last interval end time
      private float frames = 0; // frames over current interval
      private float fps; // current FPS
   // <--- END
   private string textAreaContent = "";
   private Rect windowRect = new Rect (7f, 180f, 250f, 50f);
   private Rect buttonRect = new Rect (207f, 18f, 38f, 17f);
   private Vector2 scrollPosition; // the variable to control where the scrollview 'looks' into its child elements
   // you need to create the following style as you like to make possible to use them
   private GUIStyle debugTextArea;
   private GUIStyle yellowLabel;
   private GUIStyle redLabel;
   private GUIStyle greenLabel;
   private GUIStyle captionLabel;
   private GUIStyle lineLabel;
   // the flag to check if enable or not the features of your project
   private bool feature1Flag = true;
   private bool feature2Flag = true;

   public void Start () {
      // FPS variables initialization
      lastInterval = Time.realtimeSinceStartup;
      frames = 0;
      // GUI styles needed
      debugTextArea = guiSkin.GetStyle ("DebugTextArea");
      yellowLabel = guiSkin.GetStyle ("YellowLabel");
      redLabel = guiSkin.GetStyle ("RedLabel");
      greenLabel = guiSkin.GetStyle ("GreenLabel");
      captionLabel = guiSkin.GetStyle ("CaptionLabel");
      lineLabel = guiSkin.GetStyle ("LineLabel");		
   } // Start
	
   public void Update () {
      calculateFPS ();
      updateDebugDataValues ();
   } // Update
	
   public void OnGUI () {
      // make a popup window
      windowRect = GUILayout.Window (0, windowRect, fillWindow, "DEBUG Window");
      // the window can be dragged around by the users - make sure that it doesn't go offscreen.
      windowRect.x = Mathf.Clamp (windowRect.x, 0.0f, Screen.width - windowRect.width);
      windowRect.y = Mathf.Clamp (windowRect.y, 0.0f, Screen.height - windowRect.height);
   } // OnGUI
	
   private void fillWindow (int windowID) {
      // make the window be draggable only in the top 20 pixels.
      GUI.DragWindow (new Rect (0f, 0f, (float) System.Decimal.MaxValue, 20f));
      // the label for first window part
      GUILayout.Label ("Marked Variables Status", captionLabel);
      // we are going to create the text area inside a scroll view to make sossible to scroll the content if necessary
      scrollPosition = GUILayout.BeginScrollView (scrollPosition, GUILayout.Height (120));
         GUILayout.TextArea (textAreaContent, debugTextArea, (GUILayoutOption[]) null);
      GUILayout.EndScrollView ();
      // the clear button
      // N.B. by pressing this button you will clear all ArrayList elements so
      //      you cannot no more see the  informations loaded in the current
      //      instantiated objects
      if (GUI.Button (buttonRect, "Clear")) {
         // delete the text area content
         textAreaContent = "";
         // delete all ArrayList items
         DebugManager.clearItems ();
      } // if
      // divider
      GUILayout.Label ("", lineLabel);
      // the label for second window part
      GUILayout.Label ("Others DEBUG features", captionLabel);
      // write the FPS value with 3 different colors depending by values
      if (fps > 30)
         GUILayout.Label ("FPS: " + fps.ToString ("f2"), greenLabel);
      else 
         if (fps > 10)
            GUILayout.Label ("FPS: " + fps.ToString ("f2"), yellowLabel);
         else
            GUILayout.Label ("FPS: " + fps.ToString ("f2"), redLabel);
      // create the toggles button by arrange them horizontally
      GUILayout.BeginHorizontal ();
         bool feature1FlagNew = GUILayout.Toggle (feature1Flag, "Feature1", (GUILayoutOption[]) null);
         bool feature2FlagNew = GUILayout.Toggle (feature2Flag, "Feature2", (GUILayoutOption[]) null);
      GUILayout.EndHorizontal ();
      if (feature1Flag  !feature1FlagNew) {
         /*TODO - disable feature 1*/
         feature1Flag = false;			
      } // if
      if (!feature1Flag  feature1FlagNew) {
         /*TODO - enable feature 1*/
         feature1Flag = true;
      } // if
      if (feature2Flag  !feature2FlagNew) {
         /*TODO - disable feature 2*/
         feature2Flag = false;			
      } // if
      if (!feature2Flag  feature2FlagNew) {
         /*TODO - enable feature 2*/
         feature2Flag = true;
      } // if
   } // fillWindow

   private void calculateFPS () {
      ++frames;
      float timeNow = Time.realtimeSinceStartup;
      if (timeNow > lastInterval + updateInterval) {
         fps = (float) (frames / (timeNow - lastInterval));
         frames = 0;
         lastInterval = timeNow;
      } // if
   } // calculateFPS
	
   private void updateDebugDataValues () {
      // get the reference to the DebugData container
      ArrayList content = DebugManager.getItems ();
      // the temporary values
      string temp = "";
      // fill the data from container
      for (int i = 0; i < content.Count; i++) {
         object obj = content[i];
         if (obj.GetType () == typeof (DebugData))
            temp += ((DebugData) obj).getDataName () + " = " + ((DebugData) obj).getDataValue () + "\n";
      } // for
      // assign the read content to the text area.
      // N.B. if you don't do this, every frame you will add to the text area all the same informations
      textAreaContent = temp;
   } // updateDebugDataValues
	
} // DebugGUI

As you can see, this class provides also an FPS counter. I’ve only used the FPSCounter suggested in the Time.realtimeSinceStartup by Unity documentation.

And there is an example class that will use this system:

using UnityEngine;
using System.Collections;

public class AnyClassOfProject : MonoBehaviour, ... {
   .
   .
   .
   // all the debug value to show if DEBUG MODE is enabled
   private DebugData dd1;
   private DebugData dd2;
   private DebugData dd3;
   .
   .
   .
   public void OnDisable () {
      if (DebugManager.DEBUG_ENABLED)
         DebugManager.removeDebugData (dd1);
         DebugManager.removeDebugData (dd2);
         DebugManager.removeDebugData (dd3);
         .
         .
         .
      } // if
   } // OnDisable

   void Start () {
      .
      .
      .
      if (DebugManager.DEBUG_ENABLED) {
         dd1 = DebugManager.createDebugData ("string1 to show in DebugWindow");
         dd2 = DebugManager.createDebugData ("string2 to show in DebugWindow");
         dd3 = DebugManager.createDebugData ("string3 to show in DebugWindow");
         .
         .
         .
      } // if
   } // Start
   
   void Update () {
      .
      .
      .
      if (DebugManager.DEBUG_ENABLED) {
         dd1.setDataValue ("the value of data1 to show");
         dd2.setDataValue ("the value of data2 to show");
         dd3.setDataValue ("the value of data3 to show");
         .
         .
         .
      } // if
   } // Update

   .
   .
   .
   
} // AnyClassOfProject

Now you have to attach the GUI to a GameObject and the game is done !!!

Here is a screenshot of mine customized DEBUG Window

Please, for improvements, questions, suggestions and others… fell free to live a reply.
THANKS for your interest !!!

very nice job, thanks for sharing with the community!

Nice work.

We also have a free console on our tools page that also provides command binding, custom logging, and a different way to track watch variables.

http://www.ennanzus-interactive.com/developer/DebugConsole/

Feel free to check it out, and perhaps merge the features of both.

Jashan also had a slick logger posted around here somewhere as well.

-Jeremy

Thank you very much: your work is really nice !!!
I’ll take a look to see if I can use some of the features you’re developing. :smile:

Hi, i really think you should use this one: http://u3d.as/content/kolmich-creations/kgfdebug/2Yy

It has 5 log levels, log categories, stacktrace levels, category and log search, different skins, copy to file and much more. It is also extendable by implementing the KGFIDebug interface…

Way to resurrect a 4 year old thread to recommend something that didn’t exist back then. :wink: