0

Iam trying to load my "PlayerHealth" Script to my "GameOverManager" to check my currentHealth from the PlayerHealth-Script.

If the current health is "0" - I want to trigger an animation.

The problem is, that Unity gives me an error with following message:

"NullReferenceException: Object reference not set to an instance of an object GameOverManager.Update () (at Assets/GameOverManager.cs:32)"

Here is the piece of Code of my GameOverManager:

public class GameOverManager : MonoBehaviour {

    public PlayerHealth playerHealthScript;
    public float restartDelay = 5f;
    Animator anim;
    float restartTimer;

    private void Awake()
    {
        anim = GetComponent<Animator>();
    }

    private void Update()
    {
        playerHealthScript = GetComponent<PlayerHealth>();
        if (playerHealthScript.currentHealth <= 0) {
            anim.SetTrigger("GamerOver");
            restartTimer += Time.deltaTime;
            if (restartTimer >= restartDelay) {
                SceneManager.LoadScene(2);
            }
        }       
    }
}

The error is triggered on the following line:

if (playerHealthScript.currentHealth <= 0)

Here is the hierarchy - FPSController holds "PlayerHealth" - HUDCanvas holds "GameOverManager:

enter image description here

Here are the inspectors:

enter image description here

enter image description here

Here is the code of "PlayerHealth":

  using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.SceneManagement;

public class PlayerHealth : MonoBehaviour
{
    public int startingHealth = 100;                            // The amount of health the player starts the game with.
    public int currentHealth;                                   // The current health the player has.
    public Slider healthSlider;                                 // Reference to the UI's health bar.
    public Image damageImage;                                   // Reference to an image to flash on the screen on being hurt.
    public AudioClip deathClip;                                 // The audio clip to play when the player dies.
    public float flashSpeed = 5f;                               // The speed the damageImage will fade at.
    public Color flashColour = new Color(1f, 0f, 0f, 0.1f);     // The colour the damageImage is set to, to flash.

    public float restartDelay = 5f;

   //Animator anim;                                              // Reference to the Animator component.
    public AudioSource playerAudio;                                    // Reference to the AudioSource component.
  //  PlayerMovement playerMovement;                              // Reference to the player's movement.
  //  PlayerShooting playerShooting;                              // Reference to the PlayerShooting script.
    bool isDead;                                                // Whether the player is dead.
    bool damaged;                                               // True when the player gets damaged.

void Awake()
{
    // Setting up the references.
  //  anim = GetComponent<Animator>();
 //   playerAudio = GetComponent<AudioSource>();
//    playerMovement = GetComponent<PlayerMovement>();
//    playerShooting = GetComponentInChildren<PlayerShooting>();

    // Set the initial health of the player.
    currentHealth = startingHealth;


}


void Update()
{
    // If the player has just been damaged...
    if (damaged)
    {
        // ... set the colour of the damageImage to the flash colour.
       damageImage.color = flashColour;
    }
    // Otherwise...
    else
    {
        // ... transition the colour back to clear.
       damageImage.color = Color.Lerp(damageImage.color, Color.clear, flashSpeed * Time.deltaTime);
    }

    // Reset the damaged flag.
    damaged = false;


    }




public void TakeDamage(int amount)
{
    // Set the damaged flag so the screen will flash.
    damaged = true;

    // Reduce the current health by the damage amount.
    currentHealth -= amount;

    playerAudio.Play();

    Debug.Log("PLayer Health: " + currentHealth);

    // Set the health bar's value to the current health.
    healthSlider.value = currentHealth;

    // Play the hurt sound
    playerAudio.Play();

    // If the player has lost all it's health and the death flag hasn't been set yet...
    if (currentHealth <= 0 && !isDead)
    {
        // ... it should die.
        Death();
    }
}


void Death()
{
    // Set the death flag so this function won't be called again.
    isDead = true;

    Debug.Log("In der Death Funktion");
1zz0
  • 163
  • 2
  • 15
  • 1
    Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – FCin Feb 17 '18 at 16:22
  • what version of Unity are you using? try to check on GetComponent and debug through if playerHealthScript is getting the object at runtime. – zhack Feb 17 '18 at 16:27

1 Answers1

2

First of all, you don't need, or better, you SHOULD NOT, use GetComponent inside Update, it's a very slow method and it impacts a lot the performance.

So, change your code to this:

public class GameOverManager : MonoBehaviour {

    public PlayerHealth playerHealthScript;
    public float restartDelay = 5f;
    private Animator anim;
    private float restartTimer;

    private void Awake() {
        anim = GetComponent<Animator>();
        //No need for GetComponent<PlayerHealth>() if you assign it in the Inspector
        //playerHealthScript = GetComponent<PlayerHealth>();
    }

    private void Update() {
        if (playerHealthScript.currentHealth <= 0) {
            anim.SetTrigger("GamerOver");
            restartTimer += Time.deltaTime;
            if (restartTimer >= restartDelay) {
                SceneManager.LoadScene(2);
            }
        }
    }
}

Moreover, your bug happens most probably because in the Inspector you assigned to the playerHealthScript variable the game object containing the PlayerHealth script. But, since you try in Update to get the script component again but this time from the game object that has the GameOverManager script (and I assume it doesn't have the PlayerHealth script), you get the NullReference since that script can't be found on this game object.

So, as you can see from the two lines commented out in my code, you actually don't need to get that component from script, just assign it via Inspector and you're good to go.

Galandil
  • 3,713
  • 1
  • 10
  • 22
  • Thank You for your fast response. – 1zz0 Feb 17 '18 at 16:35
  • If the answer solves your problem, please tag it as accepted by clicking on the gray checkmark that you can find on the left of my answer. – Galandil Feb 17 '18 at 16:36
  • I tried to put in my Script from the inspector, but i cant drag it in. It does not take it. Maybe I have to declare the variable "PlayerHealth" differently? – 1zz0 Feb 17 '18 at 16:36
  • No, you don't have to drag the script directly from the Assets. You have to attach the `PlayerHealth` script to a game object in the Hierarchy (thus making it a `Component` of that game object), then drag that game object **with** the script in the `PlayerHealth` field of the game object containing the `GameOverManager` script. – Galandil Feb 17 '18 at 16:38
  • I tried it - the PlayerHealth Script is assigned to my FPSController. But if I assign the FPSController to my GameOver scipt, i get two Errors of the same type – 1zz0 Feb 17 '18 at 16:44
  • 1
    Please provide screenshots of the Inspector of both your FPSController game object and your Game Over game object and your `PlayerHealth` script code. – Galandil Feb 17 '18 at 16:48
  • is there maybe any other possibility to load my "PlayerHealth" Script in my "GameOverManager" environment programmatically? – 1zz0 Feb 17 '18 at 17:42
  • You have to drag the `FPSController` game object inside this field: https://imgur.com/a/2jPyy - There're multiple ways to get the reference programmatically, you can use for example `playerHealthScript = GameObject.Find("FPSController").GetComponent();` – Galandil Feb 18 '18 at 11:09