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

标签 c# unity-game-engine gameobject

我检查了所有内容,但找不到有效的答案(或者至少我了解如何实现)。

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

enter image description here

这是我针对有问题的类的 Start 方法。

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 个小时,除了这个之外,我还设法自己克服了所有障碍

最佳答案

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

GameStateManager.PlayerScored += Start;

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

我认为发生的情况是,您将委托(delegate)添加到您的 PlayerScored 事件中,然后当您更改场景时该事件不会重置。当您第二次返回场景时,BallMovement 类的实例已被删除,当该事件触发时,您会收到错误 The object of类型“BallMovement”已被销毁,但您仍在尝试访问它

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

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

解决这个问题的方法是将该功能移出启动位置,并在游戏对象被销毁时从事件中删除委托(delegate)。请考虑以下问题:

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

// ...

关于c# - 类型 'BallMovement'的对象已被销毁,但您仍在尝试访问它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72323533/

相关文章:

c# - 为什么我的 ELF 哈希实现有如此高的冲突率

C# JSON 解析与子字符串

c# - 如何为 EF 6、Oracle DB、 Controller 脚手架调试和修复 'Exception has been thrown by the target of an invocation'

c# - 在 C# 中播放声音

ios - 在 Xcode 上构建并在 Testflight 上测试后,应用程序启动时出现粉红色屏幕和空白屏幕

c# - 如何通过压缩纹理来节省尽可能多的内存

c# - Avatar 类的构造函数返回 null

unity-game-engine - 以正确的方式复制游戏对象 Unity 5

c# - Unity 中游戏对象的水平重力

unity-game-engine - 从另一个游戏对象的脚本设置变换