Can't understand this NullReferenceException error I keep getting [SOLVED]

I’ve tried everything I can think of and I still can’t figure it out; it shouldn’t be null; I’ve defined it.

Here’s the relevant code:

public class Control : MonoBehaviour
{
    public AudioSource DoorLocked;
    protected bool[] hasKey;
    [HideInInspector]
    public List<int> locked;


    private void Start()
    {
        hasKey = new bool[30];

        List<int> locked = new List<int> { 0, 3, 8, 9, 10, 13, 14, 15, 16, 17, 18, 19, 20, 24, 25, 28, 29 };

        for (int i = 0; i < hasKey.Length; i++)
        {
            hasKey[i] = !locked.Contains(i);
        }
    }


    public void OpenDoor(int x, Animator anim)
    {
        if (hasKey[x])
        {
            anim.SetBool("open", !anim.GetBool("open"));
        }

        else
        {
            DoorLocked.Play();
        }
    }
}

but then when I call the OpenDoor function anywhere, I get an error re: “hasKey[×]”

I must be missing something basic, I know, but any help at all would be appreciated.

Maybe change this line

to

if (x >= 0 && x < hasKey.Length && hasKey[x])

to be sure, that x is a valid value. You could also use Debug.Log(x, gameObject), to find out the value of x and the script it is called at. If you still have the problem afterwards, please post the whole error message.

1 Like

Debug Log says the value of x is 0.
Here’s the whole error message:
"
NullReferenceException: Object reference not set to an instance of an object
Control.OpenDoor (Int32 x, UnityEngine.Animator anim) (at Assets/Scripts/Control/Control.cs:77)
DoorOpenCloseControl.Update () (at Assets/Scripts/Doors/DoorOpenCloseControl.cs:26)
"

(DoorOpenCloseControl.Update() is where I try to call OpenDoor() later on)

Ah okay. I guess you’ve been looking at the wrong line. The error is hidden here:

hasKey = !locked.Contains(i);

it should be

hasKey[i] = !locked.Contains(i);

Interesting that this statement compiles.

1 Like

Oops, there must have been an error when I copied it over, because in code it is hasKey

You’re not showing the entirety of the code so it’s a bit hard to tell but judging by the error - anim is null or DoorLocked is null.

Changed it a bit but here’s Control:

public class Control : MonoBehaviour
{

    [HideInInspector]
    public bool flashlight, flashdrive, disk, newHouse, xMas95, goldfinchVHS;
    protected bool[] hasKey;
    [HideInInspector]
    public List<int> locked;

    private void Start()
    {
        hasKey = new bool[30];
        flashlight = false;
        flashdrive = false;
        disk = false;
        newHouse = false;
        xMas95 = false;
        goldfinchVHS = false;

        List<int> locked = new List<int> { 0, 3, 8, 9, 10, 13, 14, 15, 16, 17, 18, 19, 20, 24, 25, 28, 29 };

        for (int i = 0; i < hasKey.Length; i++)
        {
            hasKey[i] = !locked.Contains(i);
        }
    }

    public bool CheckCollision(Collider obj)
    {
        RaycastHit hit;
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out hit))
        {
            if (hit.collider == obj.GetComponent<Collider>()) return true;
            else return false;
        }
        else return false;
    }  
}

and here’s the door script:

public class DoorOpenCloseControl : Control
{

    Animator doorAnim;
    public int doorNumber;
    Collider doorColl;
    public AudioSource DoorLocked;

    private void Start()
    {
        DoorLocked = GetComponent<AudioSource>();
        doorColl = gameObject.GetComponent<Collider>();
        doorAnim = gameObject.GetComponent<Animator>();
    }

    private void Update()
    {
        if (Input.GetButton("Fire1"))
        {
            if (CheckCollision(doorColl))
            {
                if (hasKey[doorNumber])
                {
                    doorAnim.SetBool("open", !doorAnim.GetBool("open"));
                }
                else
                {
                    DoorLocked.Play();
                }
            }
        }
    }
}

And the NullReferenceException says “if (hasKey[doorNumber])” is the problem.

Control.Start is never called in DoorOpenCloseControl.Start so the array is never populated. If you want to inherit that behavior then make Control.Start protected virtual and make DoorOpenCloseControl.Start protected override and call base.Start() inside it.

1 Like

The start function on the base class is not executed, only the start function on the DoorOpenCloseControl class is. All your setup code in the base class is never run and your hasKey dictionary is null.

edit - damn kelso beat me to it :stuck_out_tongue:

1 Like

It works now! Thank you so much!!!

(Unfortunately, now I have a new problem in that it resets which doors are locked each time I click on a door, but I’m working on it.)