Search Unity

NullReferenceException

Discussion in 'Scripting' started by Hosomi, Feb 8, 2018.

  1. Hosomi

    Hosomi

    Joined:
    Jan 3, 2018
    Posts:
    8
    When pressing the play button, my player controller immediately becomes disabled, I assume it's something to do with the error message:
    NullReferenceException: Object reference not set to an instance of an object
    Player.PlayerController.Awake () (at Assets/Scripts/PlayerController.cs:57)
    Code (CSharp):
    1. private SpellSlot[] SpellArray;
    2. ...
    3.  
    4. void Awake()
    5.         {
    6.             CameraLocked = false;
    7.             rb = GetComponent<Rigidbody>();
    8.  
    9.             SpellArray = new SpellSlot[4];
    10.             int Y = Screen.height - 110;
    11.             SpellArray[0].GUISize = new Rect(10, Y, 100, 100);    //Line 57
    12.             SpellArray[1].GUISize = new Rect(120, Y, 100, 100);
    13.             SpellArray[2].GUISize = new Rect(230, Y, 100, 100);
    14.             SpellArray[3].GUISize = new Rect(340, Y, 100, 100);
    15.         }
    I can't tell what's actually wrong with this. Supposedly the array of objects isn't instantiated, but it very clearly is.
    EDIT: SpellSlot is a class with a constructor. Is the constructor not being called on instantiation?
     
    Last edited: Feb 8, 2018
  2. MaxGuernseyIII

    MaxGuernseyIII

    Joined:
    Aug 23, 2015
    Posts:
    315
    Unless SpellSlot is a struct, you're going to need to initialize each cell in that array.
     
  3. Boz0r

    Boz0r

    Joined:
    Feb 27, 2014
    Posts:
    419
    The array is instantiated, yes, but it's empty. You're trying to access elements that aren't there yet.
     
  4. Hosomi

    Hosomi

    Joined:
    Jan 3, 2018
    Posts:
    8
    SpellSlot is a class. Is the constructor not being called?
    Also, I'm trying to set the elements, not read them
     
  5. Boz0r

    Boz0r

    Joined:
    Feb 27, 2014
    Posts:
    419
    No, the constructors aren't called. You've just made an empty array of size 4, that CAN contain SpellSlot objects.

    And your lines 11 - 14 don't set the elements, they try to retrieve the elements and set their GUISize.
     
  6. Hosomi

    Hosomi

    Joined:
    Jan 3, 2018
    Posts:
    8
    How do I put SpellSlot objects into the array in that case?

    Alternatively, if I convert SpellSlot into a struct instead of a class, would that resolve the issue?
     
  7. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Hmm.. I'm not sure what your constructor is, but:
    Code (csharp):
    1. for(int i = 0; i < SpellArray.Length; ++i)
    2.    SpellArray[i] = new SpellSlot();
     
  8. Hosomi

    Hosomi

    Joined:
    Jan 3, 2018
    Posts:
    8
    This hasn't worked, nor has changing the declaration of the array to:
    Code (CSharp):
    1. public SpellSlot[] SpellArray = new SpellSlot[] { new SpellSlot(), new SpellSlot(), new SpellSlot(), new SpellSlot() };
    This is getting incredibly frustrating
     
  9. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    How did it not work? the same error as before, do you mean?
    Feel free to post the SpellSlot class if that's relevant.
     
  10. Hosomi

    Hosomi

    Joined:
    Jan 3, 2018
    Posts:
    8
    It's still giving the NullReferenceException
     
  11. MaxGuernseyIII

    MaxGuernseyIII

    Joined:
    Aug 23, 2015
    Posts:
    315
    ...on the same line?
     
  12. Prastiwar

    Prastiwar

    Joined:
    Jul 29, 2017
    Posts:
    125
    If SpellSlot is class you need to create instance of it.

    Code (CSharp):
    1.  
    2.  
    3.         SpellArray = new SpellSlot[4];
    4.         int Y = Screen.height - 110;
    5.         int temp = 10;
    6.         int length = SpellArray.Length;
    7.         for (int i = 0; i < length; i++)
    8.         {
    9.             SpellArray[i] = new SpellSlot();
    10.            // You'll achieve the same result, but it's better solution than "manual" writing.
    11.             SpellArray[i].GUISize = new Rect(temp + (i * 110), Y, 100, 100);
    12.         }
     
  13. MaxGuernseyIII

    MaxGuernseyIII

    Joined:
    Aug 23, 2015
    Posts:
    315
    I'm not sure that the number of times we explain that fact is going to help, in this case. Something else is in @Hosomi's way.
     
  14. Hosomi

    Hosomi

    Joined:
    Jan 3, 2018
    Posts:
    8
    I've made some changes, but the error is still occurring.
    I'll show everything related to the issue
    Code (CSharp):
    1. public SpellSlot[] SpellArray;
    2. ...
    3.  
    4. void Awake()
    5. {
    6.     CameraLocked = false;
    7.     rb = GetComponent<Rigidbody>();
    8.     int length = SpellArray.Length;
    9.     for (int i = 0; i < length; ++i)
    10.     {
    11.         SpellArray[i] = new SpellSlot();
    12.     }
    13. }
    14. ...
    15. void OnGUI()
    16. {
    17.     int Y = Screen.height - 110;
    18.  
    19.     int length = SpellArray.Length;
    20.     for (int i = 0; i < length; ++i)
    21.     {
    22.         GUI.Box(new Rect(10+(i*110), Y, 100, 100), SpellArray[i].name);    //This line is now where the error points
    23.     }
    24. }
    and what's left of the SpellSlot class after taking it apart trying to solve this issue
    Code (CSharp):
    1. public class SpellSlot : MonoBehaviour
    2. {
    3.     public int ID;
    4.     public string Name;
    5.     public bool Occupied;
    6.  
    7.     public SpellSlot()
    8.     {
    9.         ID = 0;
    10.         Name = "";
    11.         Occupied = false;
    12.     }
    13. }
     
  15. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Of course, I didn't realize (or think to ask) if SpellSlot is a MonoBehaviour. If it doesn't have to be one, then do not make it inherit from (that).
    If you want it to be one, you cannot create a mono behaviour with the 'new' keyword. You must AddComponent to some game object.

    You'll have to know/decide what you want to do with that.
     
  16. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    As methos5k is saying, a MonoBehaviour needs to be a component attached to a GameObject. If that is what you want, then you should create a prefab of a GameObject with this SpellSlot component attached, and instead of creating new SpellSlot instances you instead instantiate new GameObjects from that prefab. Then to access the SpellSlot component you would use GetComponent<SpellSlot>() on that instantiated GameObject.

    Otherwise remove MonoBehaviour.
     
  17. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Everything in C# is case sensitive. SpellSlot doesn't have a property called name, it has a property called Name.

    Your code editor, such as Visual Studio, should be pointing out these issues long before you even try compiling.
     
  18. Hosomi

    Hosomi

    Joined:
    Jan 3, 2018
    Posts:
    8
    Still giving
    NullReferenceException: Object reference not set to an instance of an object
    Player.PlayerController.Awake () (at Assets/Scripts/PlayerController.cs:55)

    This time pointing to the line
    int length = SpellArray.Length;

    I spotted that and quickly deleted that post

    commenting out the SpellArray.Length lines and just using a constant in place of length now gives the following

    NullReferenceException: Object reference not set to an instance of an object
    (wrapper stelemref) object:stelemref (object,intptr,object)
    Player.PlayerController.Awake () (at Assets/Scripts/PlayerController.cs:58)
    Code (CSharp):
    1. //int length = SpellArray.Length;
    2. for (int i = 0; i < 4; ++i)
    3. {
    4.     SpellArray[i] = new SpellSlot(); //Error now points to this line
    5. }
     
  19. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
  20. Hosomi

    Hosomi

    Joined:
    Jan 3, 2018
    Posts:
    8
    Why are they so bloody awkward to work with? C# isn't my first language, but it has a reputation of being easy to learn, yet using an array of objects is so incredibly unintuitive

    And I've read these tutorials, but they don't seem to be at all relevant

    Regardless, I've changed the declaration of SpellArray and it works now, but I can't say I've learnt much from the experience
     
  21. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Lists were created partly because arrays are horrible to work with. I use Lists whenever I don't have to use an array.

    Simple example:
    Code (csharp):
    1. List<SpellSlot> SpellList = new List<SpellSlot>();
    2. SpellList.Add(new SpellSlot());
    3. int length = SpellList.Count;
    4.  
    5. foreach (SpellSlot ss in SpellList)
    6. {
    7.     ss.Name = "New Name";
    8.     Debug.Log(ss.Name);
    9. }
     
    Last edited: Feb 10, 2018