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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Not another NullReferenceException!

Discussion in 'Scripting' started by Fairwell, Jun 24, 2015.

  1. Fairwell

    Fairwell

    Joined:
    Nov 21, 2014
    Posts:
    4
    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:

    Code (CSharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections;
    4. using Random = UnityEngine.Random;
    5.  
    6. public class BoardManager : MonoBehaviour {
    7.  
    8.     public int columns = 10;
    9.     public int rows = 13;
    10.     public int mines = 10;
    11.     public GameObject square;
    12.     private Transform boardHolder;
    13.     public static Element[,] elements;
    14.  
    15.     void BoardSetup(){
    16.         boardHolder = new GameObject ("Board").transform;
    17.         elements = new Element[rows,columns];
    18.         for (int x = 0; x < columns; x++) {
    19.             for (int y = 0; y < rows; y++) {
    20.                 GameObject instance = Instantiate(square, new Vector3(x,y,0f), Quaternion.identity) as GameObject;
    21.                 instance.transform.SetParent(boardHolder);
    22.             }
    23.         }
    24.     }
    25.  
    26.     void LayMineAtRandom(){
    27.         int randx;
    28.         int randy;
    29.  
    30.         for (int i = 0; i < mines; i++) {
    31.             randx = Random.Range (0,rows-1);
    32.             randy = Random.Range (0,columns-1);
    33.             if(elements[randx,randy].isMine){
    34.                 i--;
    35.             }else{
    36.                 elements[randx,randy].isMine = true;
    37.             }
    38.         }
    39.     }
    40.  
    41.     // Uncover all Mines
    42.     public static void uncoverMines() {
    43.         foreach (Element e in elements)
    44.             if (e.isMine)
    45.                 e.loadTexture(0);
    46.     }
    47.  
    48.     public void SetupScene() {
    49.         BoardSetup ();
    50.         LayMineAtRandom ();
    51.         uncoverMines ();
    52.     }
    53. }
    My Element script as well:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Element : MonoBehaviour {
    5.  
    6.     public bool isMine;
    7.     // Different Textures
    8.     public Sprite[] emptyTextures;
    9.     public Sprite mineTexture;
    10.  
    11.     // Use this for initialization
    12.     void Start () {
    13.         // Register in Array
    14.         int x = (int)transform.position.x;
    15.         int y = (int)transform.position.y;
    16.         BoardManager.elements[x, y] = this;
    17.     }
    18.  
    19.     // Load another texture
    20.     public void loadTexture(int adjacentCount) {
    21.         if (isMine)
    22.             GetComponent<SpriteRenderer>().sprite = mineTexture;
    23.         else
    24.             GetComponent<SpriteRenderer>().sprite = emptyTextures[adjacentCount];
    25.     }
    26. }
    Any advice is greatly welcomed, thank you. :)
     
  2. SquarePieStudios

    SquarePieStudios

    Joined:
    Apr 22, 2015
    Posts:
    33
    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:
    Code (CSharp):
    1. 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!
     
    Fairwell likes this.
  3. Fairwell

    Fairwell

    Joined:
    Nov 21, 2014
    Posts:
    4
    Aha! That does the trick. Thank you very much :)

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

    SquarePieStudios

    Joined:
    Apr 22, 2015
    Posts:
    33
    Happy to help :D