A simple helper for class for public Inspector variables

I have had some use of this little script, so I thought I’d share it.

When working with level designers, I have often found the need to create some more descriptive error messages than a NullReferenceException when some public inspector variable is needed before the code will work properly.

So to begin with, I had maybe 50 different class files that all started with something like:

void Awake()
{	
	if (winFieldBackground != null)
	{
		winFieldBackground.SetActiveRecursively(false);
	}
	else
	{
		log.Error("Define Win Field Background in the inspector.");
	}
	
	if (winFieldBig == null)
	{
		log.Error("Define Win Field Big in the inspector.");
	}			
	
	if (winFieldFront != null)
	{
		winFieldFront.SetActiveRecursively(false);
	}
	else
	{
		log.Error("Define Win Field Front in the inspector.");
	}
	
	if (winFieldHighlighted != null)
	{
		winFieldHighlighted.SetActiveRecursively(false);
	}
	else
	{
		log.Error(GameConfig.CUSTOM_INSPECTOR_ERROR("WinFieldHighligted GameObject"));
	}
	
	if (winFieldActivated == null)
	{
		log.Error(GameConfig.CUSTOM_INSPECTOR_ERROR("WinFieldActivated Particle System"));
	}			
}

It could also sort of cludder the code, if I always had to make sure something wasn’t null before doing something else, just for the sake of level designers/graphic artists/whoever who was not code-savvy.

So I made a small GameObjectHelper class which among other things had this little snippet:

using UnityEngine;

using System;
using System.Reflection;

using GameLib.Logging;

namespace GameLib.UnityExtensions
{
	public static class GameObjectHelper
	{
		public static void AssertInspectorVariables(object c)
		{
		 	FieldInfo[] fields = c.GetType().GetFields();
			foreach (FieldInfo f in fields)
			{
				if (f.FieldType == typeof(GameObject))
				{
					if (f.GetValue(c).Equals(null))
					{
						log.Error(GameConfig.CUSTOM_INSPECTOR_ERROR(f.Name));
					}
				}
			}
		}
	}
}

So I have this custom error script that gives some generic error messages, but it could just as well have been a Debug.Log()

So now, I can just write this in the beginning of my scripts:

void Awake()
{
	GameObjectHelper.AssertInspectorVariables(this);
}

I don’t know if this is trivial, but it was cool to me.

Hope this can be of use.
/Kas

I made similar script that walk through all scripts and check the that public variables are set.
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.