【问题标题】:Unity - NullReferenceException in my GameOverManagerUnity - 我的 GameOverManager 中的 NullReferenceException
【发布时间】:2018-02-17 16:13:43
【问题描述】:

我正在尝试将我的“PlayerHealth”脚本加载到我的“GameOverManager”,以从 PlayerHealth-Script 中检查我的 currentHealth。

如果当前生命值为“0” - 我想触发动画。

问题是,Unity 给我一个错误消息:

"NullReferenceException: 对象引用未设置为对象的实例 GameOverManager.Update () (at Assets/GameOverManager.cs:32)"

这是我的 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);
            }
        }       
    }
}

错误在以下行触发:

if (playerHealthScript.currentHealth <= 0)

这是层次结构 - FPSController 持有“PlayerHealth” - HUDCanvas 持有“GameOverManager:

这里是检查员:

这是“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");

【问题讨论】:

标签: unity3d nullreferenceexception


【解决方案1】:

首先,您不需要,或者更好的是,您不应该在Update 中使用GetComponent,这是一种非常缓慢的方法,并且会极大地影响性能。

所以,把你的代码改成这样:

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);
            }
        }
    }
}

此外,您的错误发生很可能是因为在 Inspector 中您为 playerHealthScript 变量分配了包含 PlayerHealth 脚本的游戏对象。但是,由于您尝试在Update 中再次获取脚本组件,但这次是从具有GameOverManager 脚​​本的游戏对象(并且我假设它没有PlayerHealth 脚本),您得到NullReference,因为在此游戏对象上找不到该脚本。

所以,从我的代码中注释掉的两行可以看出,您实际上不需要从脚本中获取该组件,只需通过 Inspector 分配它即可。

【讨论】:

  • 感谢您的快速回复。
  • 如果答案解决了您的问题,请点击我的答案左侧的灰色复选标记,将其标记为已接受。
  • 我试图从检查器中放入我的脚本,但我无法将其拖入。它不接受它。也许我必须以不同的方式声明变量“PlayerHealth”?
  • 不,您不必直接从资产中拖动脚本。您必须将PlayerHealth 脚本附加到层次结构中的游戏对象(从而使其成为该游戏对象的Component),然后使用PlayerHealth 中的脚本拖动该游戏对象包含GameOverManager 脚本的游戏对象的字段。
  • 请提供您的 FPSController 游戏对象和 Game Over 游戏对象的 Inspector 屏幕截图以及您的 PlayerHealth 脚本代码。
猜你喜欢
  • 1970-01-01
  • 2018-12-20
  • 2017-02-10
  • 2023-02-04
  • 2016-07-20
  • 1970-01-01
  • 1970-01-01
  • 2016-10-12
  • 2020-10-06
相关资源
最近更新 更多