- Home /
Object reference not set when referencing it and adding to array
Hi. I am attempting to generate a grid and storing the individual Tiles in a 2 dimensional array. But as soon as I am attempting to access the the tiles in the array I get a "null reference exception" Bellow I have included some of the code, if someone could tell me what I'm doing wrong.
Strip down grid generation script:
public class Grid : MonoBehaviour
{
public Tile[,] Map;
public int gridWidthInHexes = 10;
public int gridHeightInHexes = 10;
private void createGrid()
{
int tempTileIndex = 0;
int curMapIndexHeight = 0;
for (float y = 0; y < gridHeightInHexes; y++)
{
int curMapIndexWidth = 0;
for (float x = 0; x < gridWidthInHexes; x++)
{
var hex = (GameObject) Instantiate(Hex);
var gridPos = new Vector2(x, y);
var tempTile = hex.GetComponent<Tile>();
tempTile.TileIndex = tempTileIndex;
Map[curMapIndexWidth, curMapIndexHeight] = hex.GetComponent<Tile>();
tempTileIndex++;
curMapIndexWidth++;
}
curMapIndexHeight++;
}
}
private void Start()
{
Map = new Tile[gridWidthInHexes,gridHeightInHexes];
createGrid();
}
}
Strip down game manager script:
public partial class GameMaster : MonoBehaviour
{
private Grid grid;
public GameObject unit;
void Start()
{
grid = gameObject.GetComponent<Grid>();
}
void OnMapLoaded()
{
Debug.Log(grid.Map[1, 3].TileIndex);
}
}
The Tile script is not that interesting. It only contains some variables. Please help.
Answer by isse26 · Sep 07, 2014 at 01:10 PM
The Error massage is: NullReferenceException: Object reference not set to an instance of an object GameMaster.OnMapLoaded () (at Assets/_Scripts/GameMaster.cs:19) GameMaster._LoadedMap () (at Assets/_Scripts/GameEvents.cs:15) Grid.Start () (at Assets/_Scripts/Grid.cs:99)
Here are the entire scripts: Grid (should be attached to _GameMaster):
using System.Collections.Generic;
using UnityEngine;
public class Grid : MonoBehaviour
{
private GameMaster gameMaster;
//The Map
public Tile[,] Map;
//following public variable is used to store the hex model prefab;
public GameObject Hex;
//next two variables can also be instantiated using unity editor
public int gridWidthInHexes = 10;
public int gridHeightInHexes = 10;
//Hexagon tile width and height in game world
private float hexWidth;
private float hexHeight;
//Method to initialise Hexagon width and height
private void setSizes()
{
//renderer component attached to the Hex prefab is used to get the current width and height
hexWidth = Hex.renderer.bounds.size.x;
hexHeight = Hex.renderer.bounds.size.z;
}
//Method to calculate the position of the first hexagon tile
//The center of the hex grid is (0,0,0)
private Vector3 calcInitPos()
{
Vector3 initPos;
//the initial position will be in the left upper corner
initPos = new Vector3(-hexWidth*gridWidthInHexes/2f + hexWidth/2, 0,
gridHeightInHexes/2f*hexHeight - hexHeight/2);
return initPos;
}
//method used to convert hex grid coordinates to game world coordinates
public Vector3 calcWorldCoord(Vector2 gridPos)
{
//Position of the first hex tile
Vector3 initPos = calcInitPos();
//Every second row is offset by half of the tile width
float offset = 0;
if (gridPos.y%2 != 0)
offset = hexWidth/2;
float x = initPos.x + offset + gridPos.x*hexWidth;
//Every new line is offset in z direction by 3/4 of the hexagon height
float z = initPos.z - gridPos.y*hexHeight*0.75f;
return new Vector3(x, 0, z);
}
//Finally the method which initialises and positions all the tiles
private void createGrid()
{
Map = new Tile[gridWidthInHexes, gridHeightInHexes];
//Game object which is the parent of all the hex tiles
var hexGridGO = new GameObject("HexGrid");
int tempTileIndex = 0;
int curMapIndexHeight = 0;
for (float y = 0; y < gridHeightInHexes; y++)
{
int curMapIndexWidth = 0;
for (float x = 0; x < gridWidthInHexes; x++)
{
//GameObject assigned to Hex public variable is cloned
var hex = (GameObject) Instantiate(Hex);
//Current position in grid
var gridPos = new Vector2(x, y);
var tempTile = hex.GetComponent<Tile>();
tempTile.TilePos = gridPos;
tempTile.TileIndex = tempTileIndex;
hex.transform.position = calcWorldCoord(gridPos);
hex.transform.parent = hexGridGO.transform;
Map[curMapIndexWidth, curMapIndexHeight] = hex.GetComponent<Tile>();
tempTileIndex++;
curMapIndexWidth++;
}
curMapIndexHeight++;
}
}
//The grid should be generated on game start
private void Start()
{
gameMaster = gameObject.GetComponent<GameMaster>();
setSizes();
createGrid();
if (gameMaster != null)
{
gameMaster._LoadedMap();
}
}
}
One of the GameMaster scripts should be attached to _GameMaster :
using UnityEngine;
public partial class GameMaster : MonoBehaviour
{
private Grid grid;
public GameObject unit;
void Awake()
{
MapLoaded += OnMapLoaded;
}
void Start()
{
grid = gameObject.GetComponent<Grid>();
}
void OnMapLoaded()
{
Debug.Log("Generated Map");
Debug.Log(grid.Map[1, 3].TileIndex);
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
if (MouseClick != null)
MouseClick(0);
}
if (Input.GetMouseButtonDown(1))
{
if (MouseClick != null)
MouseClick(1);
}
if (Input.GetMouseButtonDown(2))
{
if (MouseClick != null)
MouseClick(2);
}
}
}
public partial class GameMaster
{
public delegate void LoadingDeligate();
public event LoadingDeligate MapLoaded;
public delegate void ClickEvents(int button);
public event ClickEvents MouseClick;
public void _LoadedMap()
{
if (MapLoaded != null)
MapLoaded();
}
}
The tile script is attached to the tile Prefab:
using UnityEngine;
public class Tile : MonoBehaviour
{
private int _tileIndex;
private Vector2 _tilePos;
private GameObject _unit;
private bool isHoverd;
private GameObject GMObject;
private GameMaster gameMaster;
private bool isSelected;
public Texture defultTexture;
public Texture hoverTexture;
public Texture selectedTexture;
public int TileIndex
{
get { return _tileIndex; }
set { _tileIndex = value; }
}
public Vector2 TilePos
{
get { return _tilePos; }
set
{
_tilePos = value;
Debug.Log("New TilePos: " + _tilePos);
}
}
public GameObject Unit
{
get { return _unit; }
set { _unit = value; }
}
void Start ()
{
GMObject = GameObject.FindGameObjectsWithTag("GameController")[0];
gameMaster = GMObject.GetComponent<GameMaster>();
gameMaster.MouseClick += OnButtonPress;
}
void OnButtonPress(int button)
{
if (isHoverd && button == 0)
{
renderer.material.SetTexture("_MainTex", selectedTexture);
isSelected = true;
}
else if (!isHoverd && button == 0 && !Input.GetKey(KeyCode.LeftShift))
{
renderer.material.SetTexture("_MainTex", defultTexture);
isSelected = false;
}
}
void OnMouseEnter()
{
if (!isSelected)
{
renderer.material.SetTexture("_MainTex", hoverTexture);
}
isHoverd = true;
Debug.Log("hovering: " + _tileIndex);
}
void OnMouseExit()
{
if (!isSelected)
{
renderer.material.SetTexture("_MainTex", defultTexture);
}
isHoverd = false;
}
}
Everything works with the exception of accessing the map array and the only error I get is when I'm trying to access the array with the map stored in.
Answer by digibawb · Sep 07, 2014 at 01:40 PM
Move your line:
grid = gameObject.GetComponent<Grid>();
into the Awake method.
OnMapLoaded is most likely being called before the Start method is called, so grid is still null.
Your answer
Follow this Question
Related Questions
RTS Grid Initialisation 0 Answers
NullReferenceException weird error 1 Answer
[c#] Create visible appearence of a grid using texture or models 1 Answer
Why ExecuteInEditMode Always Causes NullReferenceException Errors Even In Clamping!! 2 Answers
Can't access Array in a class instance multidimensional Array. 1 Answer