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 !!!