'BallMovement' 类型的对象已被销毁,但您仍在尝试访问它

The object of type 'BallMovement' has been destroyed but you are still trying to access it

我检查了所有 SO 但找不到有效的答案(或者至少我知道如何实施)。

我不久前才开始使用 Unity,我正在尝试制作 Pong 克隆。游戏在第一个 运行 上运行良好,但是当玩家获胜并切换到场景 2 时,您按下再次播放按钮并返回场景 1(游戏场景)我在尝试玩游戏时遇到此错误:

这是我针对有问题 class 的启动方法。

public class BallMovement : MonoBehaviour
{
    Rigidbody2D ball;
    Vector2 vel;

    // Start is called before the first frame update
    void Start()
    {
        float posY = Random.Range(-150, 150);
        ball = GameObject.FindGameObjectWithTag("Ball").GetComponent<Rigidbody2D>();
        transform.localPosition = new Vector2(-19, posY);
        vel.x = 250;
        vel.y = -150;
        ball.velocity = vel;

        GameStateManager.PlayerScored += Start;
    }
...

抱歉问了这么愚蠢/含糊的问题,但我真的卡住了,我已经在这个 pong 克隆上工作了 8 个小时,除此之外,我设法靠自己克服了所有障碍

您似乎删除/处理了 BallMovement class。我认为这是因为您删除/处理了球,并且没有使用 BallMovement class/ 脚本创建新球。

嗯,我认为你的错误可能在于这一行:

GameStateManager.PlayerScored += Start;

我猜测 GameStateManager 以某种方式在场景加载中幸存下来,无论是不会破坏的 GameObject 还是 ScriptableObject 或其他东西。

我认为正在发生的事情是您向 PlayerScored 事件添加了一个委托,然后当您更改场景时该事件没有被重置。当您第二次回到现场时,BallMovement class 的 instance 已被删除,当该事件触发时,您会得到错误 The object of type 'BallMovement' has been destroyed but you are still trying to access it.

我看到的另一种令人担忧的事情是,你有一个方法将自己添加到一个事件中 - 当你第一次 运行 Start 时,在 Unity Start 回调,您将自己添加到 PlayerScored 事件。

然后,当 PlayerScored 触发时,您将 Start 添加到 PlayerScored 事件 第二次 。然后第二次 PlayerScored 触发它触发 Start 两次,所以你添加它两次,第三个触发器现在有四个事件要调用。事件调用列表中允许重复,因此每次它在 PlayerScored 列表中时都会触发 Start,并且每次调用它时都会再次添加。

解决这个问题的方法是将该功能移出开始,并在 GameObject 被销毁时从事件中删除委托。请考虑以下内容:

public class BallMovement : MonoBehaviour
{
    Rigidbody2D ball;
    Vector2 vel;

    // Start is called before the first frame update
    void Start()
    {
        GameStateManager.PlayerScored += OnPlayerScored;
        OnPlayerScored(); // Fire this once on Start to get everything setup!
    }

    void OnPlayerScored()
    {
        float posY = Random.Range(-150, 150);
        ball = GameObject.FindGameObjectWithTag("Ball").GetComponent<Rigidbody2D>();
        transform.localPosition = new Vector2(-19, posY);
        vel.x = 250;
        vel.y = -150;
        ball.velocity = vel;
    }

    void OnDestroy()
    {
        GameStateManager.PlayerScored -= OnPlayerScored;
    }

// ...