Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resolved NullReferenceException

Discussion in 'Scripting' started by countlesschain, Feb 8, 2021.

  1. countlesschain

    countlesschain

    Joined:
    Jun 2, 2018
    Posts:
    6
    Hi, I have a script responsible for spawning in a ship and placing turrets on the turrets mount points of the ship. On line 24 (trts.Add(gun);) I am attempting to add the spawned turrets to the "trts" list however I get a NullReferenceException: Object reference not set to an instance of an object. When I comment out this specific line to add to list, the code works as intended, except the turret is not in the list. For reference, BallisticGun is a child class of Weapon. What is the problem?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Test : MonoBehaviour
    6. {
    7.     public GameObject shipfab;
    8.     public GameObject gunfab;
    9.     public List<Transform> mps;
    10.     public List<Weapon> trts;
    11.     void Start()
    12.     {
    13.         shipfab = Resources.Load ("Prefabs/BuzzardSplit Variant") as GameObject;
    14.         GameObject shipmodel = Instantiate(shipfab, new Vector3(0,0,0), Quaternion.identity);
    15.         foreach (Transform t in shipmodel.transform)if(t.name == "Mount")mps.Add(t);
    16.         Ship ship = new Ship(shipmodel, 100.0f, mps);
    17.  
    18.         gunfab = Resources.Load ("Prefabs/Models/LMG") as GameObject;
    19.         foreach (Transform t in mps){
    20.             GameObject model = Instantiate(gunfab, t.position + t.up*0.15f, t.rotation, shipmodel.transform);
    21.             BallisticGun gun = new BallisticGun(model,"Small",25.0f,10.0f);
    22.             Bullet bt = new Bullet(3.0f, 50.0f, 5.0f);
    23.             gun.loadBullet(bt);
    24.             trts.Add(gun);
    25.         }
    26.     }
    27.  
    28.     void Update()
    29.     {
    30.        
    31.     }
    32. }
    33.  
     
  2. diXime

    diXime

    Joined:
    Oct 2, 2018
    Posts:
    162
    Hello,
    if the list is new I think you must instantiate it, like this:
    public List<Weapon> trts = new List<Weapon>();

    Why the issue doesn't happen for mps depends on the context, I would assume it has been instantiated elsewhere.
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    The answer is always the same... ALWAYS. It is the single most common error ever. Don't waste your life on this problem. Instead, learn how to fix it fast... it's EASY!!

    Some notes on how to fix a NullReferenceException error in Unity3D
    - also known as: Unassigned Reference Exception
    - also known as: Missing Reference Exception
    - also known as: Object reference not set to an instance of an object

    http://plbm.com/?p=221

    The basic steps outlined above are:
    - Identify what is null
    - Identify why it is null
    - Fix that.

    Expect to see this error a LOT. It's easily the most common thing to do when working. Learn how to fix it rapidly. It's easy. See the above link for more tips.

    This is the kind of mindset and thinking process you need to bring to this problem:

    https://forum.unity.com/threads/why-do-my-music-ignore-the-sliders.993849/#post-6453695

    Step by step, break it down, find the problem.
     
  4. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    685
    Was curious about this and tested it. For a List<Transform> (or other variable/component types) instantiation is not necessary, but for a custom class like <Weapon> it is. Am assuming the instantiation of the non-custom ones is done under the hood?
    If anyone can confirm this that would be great.
     
  5. Stoicheia

    Stoicheia

    Joined:
    Jun 25, 2020
    Posts:
    27
    If you assign a list in the inspector, then explicitly instantiating the list with the new keyword is unnecessary. Otherwise you gotta instantiate a list before adding stuff to it.

    This is universally true and independent of what you put in the list.
     
    Kurt-Dekker likes this.
  6. countlesschain

    countlesschain

    Joined:
    Jun 2, 2018
    Posts:
    6
    Hi, this was the solution thank you.
    Also mps was never instantiated like this, what you see in this script is all there is for mps. There is also no use of inspector here. Someone else mentioned that because <Weapon> is a custom class is why it needed to be instantiated, I'm thinking this might be the reason
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    No, as @Stoicheia notes above, you must always initialize collections before using them.

    If serialized data exists for that property in the Unity scene or prefab associated with that instance, even if it is an empty collection serialized in there, then the Unity deserializer will actually take care of the initialization for you.

    If the serialized field has never been seen, the collection will remain null.

    You can trivially test this by creating a scene with your script without the collection and saving it, then adding the new public collection reference, then running the game. You'll see that public property is null, not an empty collection.

    EDIT: looks like Unity has changed this behavior! I tested in Unity2019.4.15 and the above is no longer true.

    EDIT #2: it's even trickier! Turns out prefabs and scenes WILL automatically create your collection, even if it never existed before... BUT... Resources.Load() will not.

    Either way, always initialize your collections if they are null. Not doing so is going to crash your game.
     
    Last edited: Feb 8, 2021
  8. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    685
    Another case is when using a class not derived from Monobehaviour, where you can't attach it to a GameObject and have it viewable in the Inspector (one example of what you were referring to). You need to explicitly initialize collections of those to use them.