Testing Public Variables in Unity

Edit 2012/12/08: A bug fix (End() did not show correct error count); change reporting: now EndCase() and End() use Debug.LogError() fuction in reporting if there were errors (otherwise Debug.Log() is used).

It is easy to forget to set a public variable of a script in Inspector and it might take some time to figure out where the problem is. The following C# program goes and checks that all public variables in a scene are set.

TestMonoBehaviorPublicVariables.cs

using System.Collections;
using System;
using System.Reflection;
using System.ComponentModel.Design;

public class TestMonoBehaviorPublicVariables : MonoBehaviour { 
    private int errCount;
    private int errCountInScript;

    void Assert(bool status, string message) {
         if(status) { 
             Debug.LogError(" Test case failed: " + message);
             errCount++;
             errCountInScript++;
         }
    }
    void EndCase(string gameObjectName, string scriptName) {
         if(errCountInScript > 0) {
		Debug.LogError(gameObjectName + " - " + scriptName + ": errors=" + errCountInScript.ToString());	
	}
	else {
		Debug.Log(gameObjectName + " - " + scriptName + ": errors=" + errCountInScript.ToString());
         }
         errCountInScript = 0;
    }

    void End(){
         if(errCount > 0) {
            Debug.LogError("Testing MonoBehavior public variable: errors=" + errCount.ToString());
         }
         else {
            Debug.Log("Testing MonoBehavior public variables: errors=" + errCount.ToString());
        }
    }

    void Start () {
         errCountInScript = 0;
         errCount = 0;
         UnityEngine.Object[] all = Resources.FindObjectsOfTypeAll(typeof(GameObject));
         foreach(GameObject go in all) {
             if(go.tag != "DontLook") { 
                 Component[] allComponents = go.GetComponentsInChildren<Component>();
                 foreach(Component c in allComponents) {
                       try{
                           RunCase(c);
                       }
                       catch(Exception e) {
                           Debug.LogException(e, go);
                       }
                 }
             } 
         }
         End();
    }

    void RunCase(Component c) {
         FieldInfo[] myField = c.GetType().GetFields();
         for(int i=0; i<myField.Length;i++) {
             string msg = String.Format("{0} - {1} ({2}): field {3} is not set", c.name, myField[i].Name, myField[i].DeclaringType, myField[i].Name);
             Assert((myField[i].GetValue(c)).ToString()=="null", msg);
         }
         EndCase(c.name, c.GetType().ToString());
    }
}

Create prefab for this script so that you can easily drop it to a scene and test all the objects. The problems are reported as errors in Console (error counts for each object and scrip are also reported as well as total number of found errors).

Drop the prefab to a scene, hit “Play” (and stop immediately), and inspect the Console.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s