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.

Published by lankoski

Petri Lankoski, D.Arts, is a Associate Professor in Game Studies at the school of Communication, Media and IT at the Södertörn University, Sweden. His research focuses on game design, game characters, role-playing, and playing experience. Petri has been concentrating on single-player video games but researched also (multi-player) pnp and live-action role-playing games. This blog focuses on his research on games and related things.

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 )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: