Search Unity

"Object reference not set to an instance of an object" after LoadScene

Discussion in 'UGUI & TextMesh Pro' started by AsaNemu, Apr 25, 2016.

  1. AsaNemu

    AsaNemu

    Joined:
    Apr 23, 2016
    Posts:
    1
    Hello!

    This is my first time posting here and I'm not entirely familiar with everything, but I'll do my best in explaining my issue.
    I'm not entirely unfamiliar with C# but I'm new to Unity all together. I'm trying to create an incremental game and currently I've got two scenes up. One scene is a simple "Start game." scene with a button to start the game. The code for that is

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class StartGame : MonoBehaviour {
    6.  
    7.     public void ChangeScene(string sceneName)
    8.     {
    9.         SceneManager.LoadScene("Test");
    10.     }
    11. }
    12.  
    That brings us to the second scene which has the issue. There are two buttons which are meant to switch between two panels. The two panels are called "HeroHire" and "ItemPanel". The code that both buttons have to switch the two panels is

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4.  
    5. public class HeroTabClick : MonoBehaviour {
    6.     public GameObject HeroHire;
    7.     public GameObject ItemPanel;
    8.  
    9.     void Start()
    10.     {
    11.         HeroHire = GameObject.FindGameObjectWithTag("HeroHire");
    12.         ItemPanel = GameObject.FindGameObjectWithTag("ItemPanel");
    13.     }
    14.        
    15.     public void Test()
    16.     {
    17.         HeroHire.SetActive(true);
    18.         ItemPanel.SetActive(false);
    19.     }
    20. }
    21.  
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4.  
    5. public class ItemTabClick : MonoBehaviour {
    6.     public GameObject HeroHire;
    7.     public GameObject ItemPanel;
    8.  
    9.     void Start()
    10.     {
    11.         HeroHire = GameObject.FindGameObjectWithTag("HeroHire");
    12.         ItemPanel = GameObject.FindGameObjectWithTag("ItemPanel");
    13.     }
    14.  
    15.     public void Test()
    16.     {
    17.         HeroHire.SetActive(false);
    18.         ItemPanel.SetActive(true);
    19.     }
    20. }
    21.  
    Now onto my issue. If I run the second scene by itself and click the two buttons to switch the panels everything works fine, but if I go through the start scene I get the following errors,

    "NullReferenceException: Object reference not set to an instance of an object
    HeroTabClick.Test () (at Assets/Scripts/HeroTabClick.cs:18)"
    and
    "NullReferenceException: Object reference not set to an instance of an object
    ItemTabClick.Test () (at Assets/Scripts/ItemTabClick.cs:18)"

    I switch to the HeroTab panel just fine, but trying to switch to the ItemTab panel just gives me a blank result and that error, and both errors point to ItemPanel.SetActive(false);

    I'm very confused since I don't know why it runs perfectly with no errors if I run that scene explicitly but if I run the start scene first it doesn't. Also, why is it only the ItemPanel that is erroring and how do I fix this?

    Hopefully I gave you guys enough information and I'll update as soon as I can if you need more information.

    Thank you in advance!
     
    twogearsoft likes this.
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Looks like ItemPanel is not being found.
    Those errors basically mean your find code is not finding the objects and you are getting null.
    Try something like this:

    Code (csharp):
    1.  
    2.     public void Test()
    3.     {
    4.         if(HeroHire == null)
    5.         {
    6.             HeroHire = GameObject.FindGameObjectWithTag("HeroHire");
    7.             if(HeroHire == null)
    8.             Debug.LogError(name + " could not find HeroHire")
    9.         }
    10.      
    11.         if(ItemPanel == null)
    12.         {
    13.             ItemPanel = GameObject.FindGameObjectWithTag("ItemPanel");
    14.             if(ItemPanel == null)
    15.             Debug.LogError(name + "  could not find ItemPanel")
    16.         }      
    17.  
    18.         HeroHire.SetActive(false);
    19.         ItemPanel.SetActive(true);
    20.     }
    Also your scripts are basically the same they just set the values inversely, you could turn them into a single script and make life easier ;)
     
  3. Fragmental

    Fragmental

    Joined:
    Jun 30, 2013
    Posts:
    61
    I know this is an old subject, but may have been having the same issue, and I found a way to solve it. Initially I had an issue with null references when I had objects I was accessing from another script. I believe the issue was related to order of operations in some way. For some reason, some variables weren't getting assigned fast enough, or something? Either way, solving one issue solved them both.

    A simplified version of the script holding the reference.

    Code (CSharp):
    1. public class RefHolder : MonoBehaviour {
    2.       public GameObject button;
    3.     public static RefHolder instance = null;
    4.  
    5.     void Awake ()
    6.     {
    7.         instance = this;
    8.     }
    9.  
    10. }

    A simplified version of the script using the reference

    Code (CSharp):
    1. public class TestBoardManager : MonoBehaviour {
    2.  
    3. GameObject button = null;
    4.  
    5.  
    6.     void Awake()
    7.     {
    8.         button = TestLoader.instance.button;
    9.         Debug.Log(button.activeSelf);
    10.  
    11.     }
    12.  
    13.  
    14.     public IEnumerator Test()
    15.     {
    16.  
    17.         Debug.Log(button.name);
    18.         Debug.Log(button.activeSelf);
    19.  
    20.     }
    21.  
    22. }

    Both the code in TestBoardManager.Awake() and the code in TestBoardManager.Test(), when called from a different script, would failed with null reference errors. For Awake(), changing it to Start() seems to have slowed it down enough to work. For Test(), adding "yield return null;" fixed that.

    Here's the new code.

    Code (CSharp):
    1. public class TestBoardManager : MonoBehaviour {
    2.  
    3.     GameObject button = null;
    4.  
    5.     //This can't be awake or it fails.
    6.     void Start()
    7.     {
    8.         button = TestLoader.instance.button;
    9.         Debug.Log(button.activeSelf);
    10.     }
    11.  
    12.  
    13.     public IEnumerator Test()
    14.    }
    15.  
    16.         //This yield needs to be before the other stuff, or it will fail.
    17.         //Something about order of operations I guess.
    18.         yield return null;
    19.         Debug.Log(button.name);
    20.         Debug.Log(button.activeSelf);
    21.  
    22.     }
    23.  
    24. }


    Since, initially, I couldn't get this problem solved, I started doing something similar to what you're doing, where I was using GameObject.Find, and I was having what seems to be the exact same problem where it would work fine if I loaded directly into the scene, but would have null reference errors if I loaded the scene from a different scene.

    A well placed "yield return null" before the code giving you the null ref error might fix your issue, or you could switch to accessing references from other scripts as I did, again using coroutines with "yield return null". There might be other ways to slow execution by a frame or less, but I don't know them.