Custom editor window with using a separate class causes Null Reference

Hi all,

I’m having a bit of trouble with a custom editor window i am writing for one of our in house tools. I have an array of game objects that my tool will use for various things. For each game object element in my array the editor script will add a game object field to the window, this works fine.

The problem is that for each game object i need to have a bool for wether or not that particular object should be active in the functions that the editor performs, I thought i might just make a class with the game object and a bool, then make an array of this class instead of just game objects, how ever the code that works fine with the array of game objects just throws a null reference exception when the array of my class is used, i’ve been trying figure out why but have had no luck.

Anyone know why, or have any ideas on how to fix this??

Thanks

Working Code:

/*CustomWindow.cs*/

//this is how i initialise the game object array
GameObject[] arrayObjects = new GameObject[10];

//this is in my editors OnGUI() function and works fine
for(int i = 0; i < arrayObjects.length; i++) {
    arrayObjects[i] = (GameObject)EditorGUILayout.ObjectField("Array Object" + (i + 1) + ":", arrayObjects[i], typeof(GameObject), true, GUILayout.Width (280)) as GameObject;
}

This code throws a null reference:

/*ArrayObject.cs*/

//ArrayObject class
class ArrayObject {
   
    GameObject obj = new GameObject();
    bool active = true;

   //... class methods below...
}

//----------------------------------------------------------

/*CustomWindow.cs*/

//initialise the array
ArrayObject[] arrayObjects = new ArrayObject[10];

//itn the OnGUI() function, the arrayObjects[i].obj = (GameObject)Editor.... line throws the error
for(int i = 0; i < arrayObjects.length; i++) {
    arrayObjects[i].obj = (GameObject)EditorGUILayout.ObjectField("Array Object" + (i + 1) + ":", arrayObjects[i].obj, typeof(GameObject), true, GUILayout.Width (280)) as GameObject;
}

Where is this line in your script?

ArrayObject[] arrayObjects = new ArrayObject[10];

EDIT: You could probably use a Dictionary for this too instead of writing a custom class.

(GameObject)EditorGUILayout.ObjectField("Array Object" + (i + 1) + ":", arrayObjects[i].obj, typeof(GameObject), true, GUILayout.Width (280)) as GameObject;

Double cast?

Ok, what I think throw your exception is the (GameObject) in front. Explicit cast cannot receive a null value and will throw an exception. While “as GameObject” (soft cast) will return null if the cast is invalid and no exception is thrown.

It’s the first instance variable of the custom window class –

using UnityEngine;
using UnityEditor;
using System;

public class CustomWindow : EditorWindow
{
	ArrayObject[] arrayObjects = new ArrayObject[10];
        
        //other variables and methods follow

}

@LightStriker
whoops didn’t even notice that double cast, feeling a little foolish now :stuck_out_tongue: thanks for pointing that one out, I removed the explicit cast and i still receive the null reference exception.

it definitely seems to be something to do with using the class instead of game objects as they work fine

One, I see you make an ArrayObject array, but the array isn’t filled with anything.

// Sets aside in memory for 10 ArrayObject references,
// however all 10 references are null.
ArrayObject[] arrayObjects = new ArrayObject[10];

So after creating the array, you should loop through them and fill the array up. You should have an initialization function somewhere, or fill the array whenever you first need it.

// Bad. Use LightStriker's for loop instead.
foreach (ArrayObject ao in arrayObjects) {
  ao.obj = new ArrayObject(); // Doesn't work. Can't assign in a foreach loop.
}

Now you can get or set arrayObjects[n].obj.

EDIT: Cannot assign references in foreach. Use LightStriker’s for loop instead!

arrayObjects[i].obj = EditorGUILayout.ObjectField("Array Object" + (i + 1) + ":", arrayObjects[i].obj, typeof(GameObject), true, GUILayout.Width (280)) as GameObject;

Would always make more sense, since “ArrayObject” is not a Unity type. What you’re getting/setting is the .obj value.

Second, you would probably need to initialize your array;

for (int i = 0; i < arrayObjects.Lenght; i++)
    arrayObjects[i] = new ArrayObject();

Don’t think you can do that. “ao” would be null, and you cannot change a collection while it’s iterating with foreach.

You’re right. Can’t assign in foreach! Gotta use the for loop instead.

Thanks Garth LightStriker I was assuming the call to new ArrayObject[10] was initialising each element as an ArrayObject, all sorted now

cheers