Unity C# 2d Breakout Clone, Null Reference Exception



在我开始之前,是的,我已经在网上找到了这个答案。我遵循了许多其他问题的建议,浏览了unity文档,并进行了多次网络搜索,但到目前为止我没有发现任何解决错误的方法。我相信有人会看一眼就知道是什么问题,但对我来说,我就是找不到。

既然已经解决了问题,问题来了。我在做一个克隆人我把一切都搞定了,一切都正常运转。我有一个静态类,负责得分和与得分相关的变量,以便其他脚本可以轻松访问它们。我想练习一些基本的保存和加载PlayerPrefs,所以我添加了一些高分。它几乎独立于其他类,但是一旦我完成了这一点,我开始在一个已经完成了几个小时的脚本中得到一个空引用异常,并且工作得很好。

我很感激你可能提供的任何帮助,以及防止下次出现此类错误的提示。对不起,这是一个很长的问题。

下面是完整的错误:

NullReferenceException: Object reference not set to an instance of an object
MenuManager.ActivateLose () (at Assets/Scripts/MenuScripts/MenuManager.cs:31)
Scoring.CheckGameOver () (at Assets/Scripts/Scoring.cs:64)
Scoring.LifeLost () (at Assets/Scripts/Scoring.cs:51)
DeadZone.OnTriggerEnter2D (UnityEngine.Collider2D other) (at Assets/Scripts/DeadZone.cs:22)

下面是上述错误中列出的三个脚本:

using UnityEngine;
using System.Collections;
public class DeadZone : MonoBehaviour 
{
    public GameObject ballPrefab;
    public Transform paddleObj;
    GameObject ball;
    void Update () 
    {
        ball = GameObject.FindGameObjectWithTag("Ball");
    }
    void OnTriggerEnter2D(Collider2D other)
    {
        //if the object that entered the trigger is the ball
        if(other.tag == "Ball")
        {
            Scoring.LifeLost();
            //destroy it, and instantiate a new one above where the paddle currently is
            Destroy(ball);
            paddleObj.transform.position = new Vector2(0, -2.5f);
            (Instantiate(ballPrefab, new Vector2(paddleObj.transform.position.x, paddleObj.transform.position.y + 0.3f), Quaternion.identity) as GameObject).transform.parent = paddleObj;
        }
    }
}

using UnityEngine;
using System.Collections;
public static class Scoring
{
    public static GameObject scoreValue;
    public static TextMesh scoreText;
    public static int score;
    static int multiplier = 0;
    static int consecutiveBreaks = 0;
    static int lives = 3;
    static int totalBricks;
    static int remainingBricks;
    public static GameObject menuManagerObj;
    public static MenuManager menuManager = new MenuManager();
    static void Awake()
    {
        scoreValue = GameObject.FindGameObjectWithTag("Scoring");
        scoreText = scoreValue.GetComponent<TextMesh>();
        menuManagerObj = GameObject.FindGameObjectWithTag("MenuManager");
        //menuManager = menuManagerObj.GetComponent<MenuManager>();
    }
    public static void BrickDestroyed()
    {
        if(scoreValue == null && scoreText == null)
        {
            scoreValue = GameObject.FindGameObjectWithTag("Scoring");
            scoreText = scoreValue.GetComponent<TextMesh>();
        }
        remainingBricks--;
        consecutiveBreaks++;
        multiplier = 1 + (consecutiveBreaks % 5);
        score += 10 * multiplier;
        CheckGameOver();
        scoreText.text = score + "";
    }
    public static void LifeLost()
    {
        consecutiveBreaks = 0;
        multiplier = 1;
        score -= 100;
        lives--;
        LivesDisplay.SetLives(lives);
        CheckGameOver();
        scoreText.text = score + "";
    }
    public static void SetBrickCount(int brickCount)
    {
        totalBricks = brickCount;
        remainingBricks = totalBricks;
    }
    public static void CheckGameOver()
    {
        //lose condition
        if(lives < 0) menuManager.ActivateLose();
        //win condition
        if(remainingBricks == 0) menuManager.ActivateWin();
    }
}

using UnityEngine;
using System.Collections;
public class MenuManager :  MonoBehaviour
{
    public GameObject winMenu;
    public GameObject loseMenu;
    public GameObject pauseMenu;
    public HighScoreManager highScores;
    bool isGamePaused = true;
    void Awake()
    {
        winMenu = GameObject.FindGameObjectWithTag("Win");
        loseMenu = GameObject.FindGameObjectWithTag("Lose");
        pauseMenu = GameObject.FindGameObjectWithTag("Pause");
    }
    public void ActivateWin()
    {
        Time.timeScale = 0f;
        winMenu.transform.position = new Vector3(0, 0, -1);
        highScores.CompareToHighScores(Scoring.score);
    }
    public void ActivateLose()
    {
        Time.timeScale = 0f;
        loseMenu.transform.position = new Vector3(0, 0, -1);
    }
    void ActivatePause()
    {
        if(isGamePaused)
        {
            Time.timeScale = 0f;
            pauseMenu.transform.position = new Vector3(0, 0, -1);
        }
        else
        {
            Time.timeScale = 1f;
            pauseMenu.transform.position = new Vector3(35, 0, -1);
        }
        isGamePaused = !isGamePaused;
    }
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Escape))
        {
            ActivatePause();
        }
    }
}

问题是Scoring不是MonoBehaviour,所以Awake方法永远不会被调用。可以尝试在静态构造函数

中初始化字段。
static Scoring()
{
    scoreValue = GameObject.FindGameObjectWithTag("Scoring");
    scoreText = scoreValue.GetComponent<TextMesh>();
    menuManagerObj = GameObject.FindGameObjectWithTag("MenuManager");
    //menuManager = menuManagerObj.GetComponent<MenuManager>();
}
或者将Awake方法设为public并从另一个MonoBehaviour中调用。

相关内容

  • 没有找到相关文章

最新更新