Not another NullReferenceException!

Hey guys, I could use some help figuring out what I need to do here. I’m very new to Unity so I’m sure I’m doing something simple and dumb.

I’m recreating classic minesweeper as a learning exercise and get the error:

NullReferenceException: Object reference not set to an instance of an object
BoardManager.LayMineAtRandom () (at Assets/Scripts/BoardManager.cs:33)

Here is my BoardManager script:

using UnityEngine;
using System;
using System.Collections;
using Random = UnityEngine.Random;

public class BoardManager : MonoBehaviour {
  
    public int columns = 10;
    public int rows = 13;
    public int mines = 10;
    public GameObject square;
    private Transform boardHolder;
    public static Element[,] elements;
  
    void BoardSetup(){
        boardHolder = new GameObject ("Board").transform;
        elements = new Element[rows,columns];
        for (int x = 0; x < columns; x++) {
            for (int y = 0; y < rows; y++) {
                GameObject instance = Instantiate(square, new Vector3(x,y,0f), Quaternion.identity) as GameObject;
                instance.transform.SetParent(boardHolder);
            }
        }
    }

    void LayMineAtRandom(){
        int randx;
        int randy;

        for (int i = 0; i < mines; i++) {
            randx = Random.Range (0,rows-1);
            randy = Random.Range (0,columns-1);
            if(elements[randx,randy].isMine){
                i--;
            }else{
                elements[randx,randy].isMine = true;
            }
        }
    }

    // Uncover all Mines
    public static void uncoverMines() {
        foreach (Element e in elements)
            if (e.isMine)
                e.loadTexture(0);
    }

    public void SetupScene() {
        BoardSetup ();
        LayMineAtRandom ();
        uncoverMines ();
    }
}

My Element script as well:

using UnityEngine;
using System.Collections;

public class Element : MonoBehaviour {

    public bool isMine;
    // Different Textures
    public Sprite[] emptyTextures;
    public Sprite mineTexture;

    // Use this for initialization
    void Start () {
        // Register in Array
        int x = (int)transform.position.x;
        int y = (int)transform.position.y;
        BoardManager.elements[x, y] = this;
    }

    // Load another texture
    public void loadTexture(int adjacentCount) {
        if (isMine)
            GetComponent<SpriteRenderer>().sprite = mineTexture;
        else
            GetComponent<SpriteRenderer>().sprite = emptyTextures[adjacentCount];
    }
}

Any advice is greatly welcomed, thank you. :slight_smile:

Rather than assigning the element to the elements map from Start within Element, this should be done during BoardSetup() by adding the following line inside the loop to create the elements:

elements[x, y] = instance.GetComponent<Element>();

This assumes that the prefab square has an Element component attached to it. This can be enforced explicitly by changing the type of square from GameObject to Element. This shouldn’t have any impact on the rest of your code (or if it does, use square.gameObject).

Hope this helps!

1 Like

Aha! That does the trick. Thank you very much :slight_smile:

Also clued me in to a fix for another error I was getting, 2 for the price of one!

1 Like

Happy to help :smile: