Failing to get Boolean Values From Array

I am trying to make it so that when the player is selecting a ship, it will check an array of boolean values to see if the specific ship is unlocked, but it keeps giving me a NullReferenceException saying that the Object Reference is not set to an instance of an object.

I’m able to get other values from the script I’m accessing, but not the bool array.
Here’s the ship selecting script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ShipSelect : MonoBehaviour {

    public LoadScene loader;

    public Sprite[] shipSelect;
    public Image shipImage;
    public Image lockedImage;
    public Text shipText;
    public int shipNum = 0;
    public bool unlocked = true;
    public AudioSource source;
    public AudioClip fail;


    // Use this for initialization
    void Start ()
    {
       
    }


    public void ChangeShip (int l_or_r)
    {
        // Add or subtract to shipNum based on which button is clicked
        shipNum += l_or_r;
        if (shipNum < 0) {
            // If shipNum is less than 0, loop to the last value
            shipNum = shipSelect.Length - 1;
        } else if (shipNum > shipSelect.Length - 1) {
            // If shipNum passes the last value, loop back to 0
            shipNum = 0;
        }

        // Check if the related ship is unlocked in GameData
        unlocked = GameData.data.unlocks [shipNum];
        shipImage.sprite = shipSelect [shipNum];
        if (unlocked != true) {
            // If not, enable the lock image over the ship sprite
            lockedImage.enabled = true;
        } else if (unlocked == true) {
            // Otherwise remove it
            lockedImage.enabled = false;
        }

        // Set the text to be the name of the ship
        if (shipNum == 0) {
            shipText.text = "Basic";
        } else if (shipNum == 1) {
            shipText.text = "Tri";
        } else if (shipNum == 2) {
            shipText.text = "TenK";
        }

    }

    public void SelectedShip ()
    {
        if (unlocked == true)
        {
            // If current ship is unlocked, play click sound and load the Game scene
            source.Play ();
            loader.LoadByIndex (1);
        }
        else
        {
            // If locked, play an error sound
            source.PlayOneShot (fail);
        }
    }
}

And here’s the GameData script (sorry it’s probably a mess, this is my first project):

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GameData : MonoBehaviour {

    public static GameData data;

    GameObject shipControl;
    public int shipNum;
    bool init = false;

    public GameObject ui;
    [HideInInspector] public Text scoreText, lifeText;


    [HideInInspector] public int highScore, deaths, asteroids_destroyed, buttroids_destroyed;
    public bool[] unlocks = new bool[8];
    [HideInInspector] public int go_score, life_score;
    int score;
    public int lives;
    Scene currentscene;

    void Awake ()
    {
        if (data == null)
        {
            DontDestroyOnLoad (gameObject);
            data = this;
        }
        else if (data != this)
        {
            Destroy (gameObject);
        }
        unlocks [0] = true;
    }

    void Start ()
    {
        score = 0;
        lives = 3;
    }

    void AddScore (int points)
    {
        if (points == 50) {
            asteroids_destroyed += 1;
        } else {
            buttroids_destroyed += 1;
        }
        score = score + points;
        if (score >= highScore) {
            highScore = score;
        }
    }

    void LoseLife ()
    {
        lives -= 1;
        deaths += 1;

        // Gets highest score in a single life
        if (score > life_score) {
            life_score = score;
        }
        // Sets end score and sends everything to game over screen
        if (lives <= 0)
        {
            go_score = score;
            GameOver();
        }
    }

    void Update ()
    {
        if (init == true) {
            // If ui is loaded, update it each frame
            scoreText.text = "Score: " + score;
            lifeText.text = "Lives: " + lives;
        } else {
            // Check if Game scene is loaded
            currentscene = SceneManager.GetActiveScene ();
            if (currentscene.name == "Game") {
                // Load ui and get it ready for updating
                ui = GameObject.FindGameObjectWithTag ("GameUI");
                scoreText = ui.GetComponentsInChildren<Text> () [0];
                lifeText = ui.GetComponentsInChildren<Text> () [1];
                init = true;
            }

        }

        if (Input.GetKey ("a") && Input.GetKey ("s") && Input.GetKey ("d") && Input.GetKey ("f")) {
            highScore = 0;
            Debug.Log ("Highscore reset");
        }
    }

    void GameOver ()
    {
        init = false;
        SceneManager.LoadScene (2);
    }



    public void OnEnable ()
    {
        if (File.Exists (Application.persistentDataPath + "/Data.dat"))
        {
            BinaryFormatter bf = new BinaryFormatter ();
            FileStream save_file = File.Open (Application.persistentDataPath + "/Data.dat", FileMode.Open);
            SaveData data = (SaveData)bf.Deserialize (save_file);
            save_file.Close ();

            highScore = data.Highscore;
            deaths = data.deaths;
            asteroids_destroyed = data.asteroids_destroyed;
            buttroids_destroyed = data.buttroids_destroyed;
            unlocks = data.unlocks;
        }
    }

    public void OnDisable ()
    {
        BinaryFormatter bf = new BinaryFormatter ();
        FileStream save_file = File.Create (Application.persistentDataPath + "/Data.dat");

        SaveData data = new SaveData ();
        data.Highscore = highScore;
        data.deaths = deaths;
        data.asteroids_destroyed = asteroids_destroyed;
        data.buttroids_destroyed = buttroids_destroyed;
        data.unlocks = unlocks;

        bf.Serialize (save_file, data);
        save_file.Close ();
    }
}

[Serializable]
class SaveData
{
    public int Highscore, deaths, asteroids_destroyed, buttroids_destroyed;
    public bool[] unlocks;
}

Anyways, any ideas would be helpful, the stuff works it I set the bool manually, but I can’t seem to get it from the array, and I don’t understand why (Though if I had to guess, it’d be because of the variable for the array, but it works for me in other scripts?).

I suppose I could just check the unlock conditions each time if I can’t figure this out, but I feel like I’m just missing something simple…

All I can think to suggest is test & determine what is null. Then work your way through to find out why. I know that’s not much of an answer but that’s all I can think of.
Just to confirm, is it this line?

unlocked = GameData.data.unlocks [shipNum];

Yep, the second I try to reference that array, it stops working… :confused:

I wouldn’t think it would matter, but maybe try to instantiate it in the start method.
public bool [ ] unlocks;

void Start(){
unlocks = new bool[8];
}

I do that all the time, but I haven’t done it with a static instance like that.
The other thing is that you might be calling it before it had time to instantiate. That would only be in the first scene, of course, since it’s DontDestroyOnLoad.

1 Like

Hmm… I think that did it… I guess I’ll just have it instantiated in Start or Awake, then load the values from the file into it. Still don’t understand it at all, but at least it’s working, lol.
Thanks for the help.

Glad ya got it solved.