簡體   English   中英

Unity C#2d Breakout克隆,空引用異常

[英]Unity C# 2d Breakout Clone, Null Reference Exception

好的,在開始之前,是的,我已經上網尋找了答案。 我遵循了關於其他多個問題的建議,通過了統一文檔,並進行了多次網絡搜索,到目前為止,我發現沒有任何東西可以解決該錯誤。 我敢肯定有人會看一眼並立即知道出了什么問題,但是對於我來說,我就是找不到。

既然這樣,那就不成問題了。 我正在制作Breakout克隆,我已完成所有工作,一切工作正常。 我有一個靜態類,負責處理評分和與分數相關的變量,以便其他腳本可以輕松訪問它們。 我想使用PlayerPrefs進行一些基本的保存和加載,因此我為高分添加了一些內容。 它幾乎獨立於其他類,但是一旦完成,我就開始在已經完成了幾個小時並且工作正常的腳本中獲取Null Reference Exception。

感謝您提供的任何幫助,以及下次如何防止此類錯誤的提示。 抱歉,這個問題太長了。

這是完整的錯誤:

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方法公開,並從另一個MonoBehaviour中調用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM