NullReferenceException on my Array...

Hey guys!

I’m trying to do an array in my game buuut, it doesn’t work and i don’t know why :frowning:

I want to hide a GameObject (Life Icons) when my character’s get hit.

I appreciate if you help me.

“NullReferenceException: Object reference not set to an instance of an object
Player.OnTriggerEnter (UnityEngine.Collider otherObject) (at Assets/scripts/Shooter/Player.cs:63)”

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {

	public float PlayerSpeed;
	public GameObject BolinhaPrefab;
	public GameObject ExplosaoPrefab;
	
	public static int Score = 0;
	public static int Lives = 5;
	
	public GameObject [] GuiLives1;

	
	public static int Missed = 0;
		
	// Update is called once per frame
	void Update () 
	{
		//Velocidade de movimento
		float antToMove = Input.GetAxis("Horizontal") * PlayerSpeed * Time.deltaTime;
		
		//Mover o Bob
		transform.Translate(Vector3.right * antToMove);
		
		// Destruir ao sair da tela
		if (transform.position.x <= -7.6f)
			transform.position = new Vector3 (7.4f, transform.position.y, transform.position.z);
		else if (transform.position.x >= 7.6f)
			transform.position = new Vector3 (-7.4f, transform.position.y, transform.position.z);
		
		if (Input.GetKeyDown("space"))
		{
			//Disparar Bolinha
			Vector3 position = new Vector3 (transform.position.x, transform.position.y + (transform.localScale.y / 2));
			Instantiate(BolinhaPrefab, position, Quaternion.identity);
		}
	}

	void OnGUI()
	{
		GUI.Label(new Rect(10, 10, 120, 20), "Score: " + Player.Score.ToString());
		GUI.Label(new Rect(10, 30, 60, 20), "Vidas: " + Player.Lives.ToString());	
		GUI.Label(new Rect(10, 50, 120, 20), "Missed: " + Player.Missed.ToString());
		
	}
	
	
	void OnTriggerEnter (Collider otherObject)
	{
		if (otherObject.tag == "enemy")
		{
			Player.Lives--;
			
			Inimigo enemy = (Inimigo)otherObject.gameObject.GetComponent("Inimigo");
			enemy.SetPositionAndSpeed();
			
			StartCoroutine(MatarBob());
			
			GuiLives1 = new GameObject[5];
 			for (int i = 0; i < 5; i++){
				GuiLives1[i].gameObject.SetActive(false);
			}
			
		
		}
	}	
	
	//Bob Morre aqui
	IEnumerator MatarBob()
	{				
		Instantiate(ExplosaoPrefab, transform.position, Quaternion.identity);
		gameObject.renderer.enabled = false;
		transform.position = new Vector3(0f, transform.position.y, transform.position.z);
		yield return new WaitForSeconds(1.5f);
		if (Player.Lives > 0)
			gameObject.renderer.enabled = true;
		else
			Application.LoadLevel(3);
	}
	
	
}
            GuiLives1 = new GameObject[5];

            for (int i = 0; i < 5; i++){

                GuiLives1[i].gameObject.SetActive(false);

            }

You instantiated the array with a size of 5 gameobjects, but you didn’t actually put any gameObjects in there, then you tried to set the null gameObjects inactive.

On lines 61-63 you have:

GuiLives1 = new GameObject[5];
    for (int i = 0; i < 5; i++){
        GuiLives1[i].gameObject.SetActive(false);
    }

You’ve set GuiLives1 as an array that can hold five GameObjects, but you haven’t actually told it what GameObjects to hold. GuiLives1* is returning null because the array doesn’t hold any references to GameObjects. If you have a GameObject or a prefab of a heart that you want to display on-screen first, you can do something like the following:*
* *void Start() { GuiLives1 = new GameObject[5]; for(int i = 0; i < GuiLives1.Length; i++) { GuiLives1[i] = (GameObject)Instantiate(heartPrefab, heartPrefabPosition, heartPrefabRotation); } }* *
Then you can remove the initialization of GuiLives1 on line 61 and just deactivate them in your for-loop on 62-64. Note that you’ll have to specify different Vector3’s for each heart’s position when you instantiate them, or else they’ll all be sitting on top of one another.

I can delete this?

GuiLives1 = new GameObject[5];
    for (int i = 0; i < 5; i++){
        GuiLives1[i].gameObject.SetActive(false);
    }

And now i can replace with this code?

void Start() {
    GuiLives1 = new GameObject[5];
    for(int i = 0; i < GuiLives1.Length; i++) {
        GuiLives1[i] = (GameObject)Instantiate(heartPrefab, heartPrefabPosition, heartPrefabRotation);
    }
}

Then you can remove the initialization of GuiLives1 on line 61 and just deactivate them in your for-loop on 62-64. Note that you’ll have to specify different Vector3’s for each heart’s position when you instantiate them, or else they’ll all be sitting on top of one another.[/QUOTE]

Not quite, you can only delete the first line out of the four that you posted.

The Start() method is a built-in MonoBehaviour method that runs once for the lifetime of the GameObject that it is attached to at the beginning of its existence. There are some caveats to when exactly it will run, but in this particular case it will run upon scene start. What that particular start method does is the following:

-Initializes GuiLives1 as an array that holds five GameObjects. Think of it as five empty glasses that hold a special type of juice (GameObject juice, in this case).
-In the for loop, it instantiates a prefab in your scene at the specified position and rotation for each index in that array, and then it assigns the instantiated prefabs to indices in your array, effectively filling each of your five glasses with delicious GameObject juice.

This Start() method replaces line 1 of

GuiLives1 = new GameObject[5];
    for (int i = 0; i < 5; i++){
        GuiLives1[i].gameObject.SetActive(false);
    }

Line 1 in that section doesn’t function properly; it initializes GuiLives1 to an empty array that can point to five GameObjects (meaning that it no longer is actually pointing to five GameObjects) right before you try to deactivate the GameObjects it holds. It’s the equivalent of throwing away your filled glasses, taking out new glasses, and then trying to drink juice out of them.

Lines 2-4 of that section are still necessary, because they loop through your array of GameObjects and disable them. Think of that loop as picking up the glasses one by one and drinking all of the juice in each of them.

With that analogy in mind, I’ll go over it one more time to try and clarify. We start out by getting out some empty glasses. We then fill the glasses with juice. We do this bit only once.

void Start() {
    GuiLives1 = new GameObject[5];   // get out five glasses that we will fill with GameObject juice
    for (int i = 0; i < GuiLives1.Length; i++) {
        GuiLives1[i] = (GameObject)Instantiate(heartPrefab, heartPrefabPosition, heartPrefabRotation);  // fill each glass with GameObject juice
    }
}

Now, if we want to disable the GameObjects, we can use the loop you have. Note that this loop disables ALL of them at once.

for (int i = 0; i < GuiLives1.Length; i++) {
    GuiLives1[i].SetActive(false);  // drink the juice from each glass (disable the GameObject at each index)
}

Should you choose to reactivate them at a later time, you can use a similar loop, except with SetActive(true).

for (int i = 0; i < GuiLives1.Length; i++) {
    GuiLives1[i].SetActive(true);  // spit the juice back up into each glass (enable the GameObject at each index)
}

Note that we never repeat initialization of the array; once we have five glasses filled with GameObject juice, we don’t want to throw those away and take out five new glasses.