Search Unity

Code works in editor but not in the build version. Operator Error?

Discussion in 'Scripting' started by Deleted User, Oct 22, 2017.

  1. Deleted User

    Deleted User

    Guest

    I have a static class that manages all of my instantiated GameObject's in a List<GameObject>. In the editor the code seems to work fine for querying the List and getting GameObject's from said List. But for some reason in my build version the List is not getting Initialized so I get an error: Object reference not set to an instance of an object error. The following is taken from my static ObjectManager class:

    Code (CSharp):
    1. public static List<GameObject> gameObjects;
    2.  
    3.     public static int GetIndexOfGameObject(string nameOfObject)
    4.     {
    5.         int i = 0;
    6.         for (int x = 0; x < gameObjects.Count; x++)
    7.         {
    8.             if (gameObjects[x].name == nameOfObject)
    9.             {
    10.                 i = x;
    11.             }
    12.         }
    13.         return i;
    14.     }
    and the following is taken from my GameManager class which is set to Initialize the above list in the Awake() method.

    Code (CSharp):
    1. private void Awake()
    2.     {
    3.         if (ObjectHolder.gameObjects == null)
    4.         {
    5.             ObjectHolder.gameObjects = new List<GameObject>();
    6.             foreach (GameObject Obj in GameObject.FindObjectsOfType<GameObject>())
    7.             {
    8.                 if (Obj.tag != "EditorOnly")
    9.                 {
    10.                     EventManager_OnObjectCreated(Obj);
    11.                 }
    12.             }
    13.         }
    14.     }
    As i said: the code works just great when i run the game in the editor, but throws a "NullReferenceException: Object reference not set to an instance of an object" in my build versions. Any advice or input would be greatly appreciated. Thanks in advance!
     
  2. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Does the error point to any of these lines? If so, which one in particular? It could also be the event that causes the exception to be thrown, a subscriber that's listening for the event or something else attempts to access the object list before you run that code... Some information is missing here.
    Can you post the complete error message including the stack-trace?

    Side note: If you already rely on a static class that acts as object holder, why does the game manager take care about that initialization? You could either initialize it directly in that static class and provided a getter, or initialize it lazily in the getter.
     
  3. Deleted User

    Deleted User

    Guest

    Here is the complete error message:
    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2.   at ObjectHolder.GetIndexOfGameObject (System.String nameOfObject) [0x0002f] in C:\Users\Devin\Documents\Unity Projects\Block Quest\Assets\Resources\Scripts\ObjectHolder.cs:12
    3.   at LightController.Update () [0x0000c] in C:\Users\Devin\Documents\Unity Projects\Block Quest\Assets\Resources\Scripts\LightController.cs:17
    4. (Filename: C:/Users/Devin/Documents/Unity Projects/Block Quest/Assets/Resources/Scripts/ObjectHolder.cs Line: 12)
    which points to this particular method in ObjectHolder.cs (line 12 is the for loop):
    Code (CSharp):
    1. public static int GetIndexOfGameObject(string nameOfObject)
    2.     {
    3.         int i = 0;
    4.         for (int x = 0; x < gameObjects.Count; x++)
    5.         {
    6.             if (gameObjects[x].name == nameOfObject)
    7.             {
    8.                 i = x;
    9.             }
    10.         }
    11.         return i;
    12.     }
    and as for LightController.cs (the line in question is the player = Object... line):
    Code (CSharp):
    1. void Update () {
    2.         player = ObjectHolder.gameObjects[ObjectHolder.GetIndexOfGameObject("Player")];
    3.         sun.transform.LookAt(player.transform);
    4.         float range = Vector3.Distance(sun.transform.position, player.transform.position);
    5.         sun.GetComponent<Light>().range = range * 1.5f;
    6.     }
     
  4. Deleted User

    Deleted User

    Guest

  5. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Well, it seems the GameManager does not exist when the LightController's Update is already running, otherwise it'd be initialized (or you somehow reset to null from somewhere else, since the field is accessible by everything in your application).
    Does the GameManager exist in the scene when it's being loaded or will something trigger instantiation?

    Either way, if you follow my suggestion above, you should be able to avoid this by letting the ObjectHolder initialize the list. It's worth to mention that you should restrict access to it, either by having a getter or by making it readonly.

    Other than that, using statics for many things will turn out to be less flexible and makes it difficult to reuse code, because you're always bound to specific types and you cannot really take advantage of common OOP principles.