MessagingSystem 导致 NullReferenceException

发布于 2024-12-09 10:06:36 字数 2060 浏览 0 评论 0原文

我决定在我的项目中实现一个简单的消息传递系统。我正在使用这个:CSharpMessenger Extended(它是用静态方法实现的)。

很奇怪的是,当我直接调用一个方法时,一切都正常工作。但是,当我使用消息传递系统广播消息时,我在某些游戏对象上收到 NullReferenceException。令我惊讶的是,添加行 if (_gameObject == null) return; 解决了问题。但是,在出现此异常的每个地方都不能添加检查对象是否为空的选项。

可能是什么问题?

这是我广播消息的代码:

public class Head : MonoBehaviour {

    public Snake snake;

    void OnControllerColliderHit (ControllerColliderHit hit)
    {
        if ( hit.gameObject.GetComponent<Terrain>() )
            return;

            //This way everything was working without any surprises.
            //snake.PropCollected( hit.gameObject.GetComponent<Prop>() );
            //Using messaging system instead
        if ( hit.gameObject.GetComponent<Prop>() )
            Messenger<Prop>.Broadcast( "prop collected", hit.gameObject.GetComponent<Prop>() );
            Destroy(hit.gameObject);

        }
    }

这是我订阅该事件并回复它的方式:

public class Snake : MonoBehaviour {

    public GameObject headBlock;

    public GameObject snakeBlocks;

    int lastSnakeBlockId;

    private GameObject FindBlockWithId( int _id )
    {
            if (!snakeBlocks) return null;    //This line somehow solves the problem; However the object is 100% assigned in the editor.

            foreach (Transform child in snakeBlocks.transform) {
                if (child.gameObject.GetComponent<SnakeBlockScript>().blockId == _id)
                {
                    return child.gameObject;
                }
            }

        return headBlock;
    }

    void Awake()
    {
        //Set up message listeners
        Messenger<Prop>.AddListener("prop collected", AddBlock);    
    }

    public void AddBlock(Prop _prop)
    {
        GameObject lastBlock = FindBlockWithId(lastSnakeBlockId - 1);
        if (!lastBlock) return;

        //Some more code
        //...
    }
}

谢谢!

I decided to implement a simple messaging system into my project. I'm using this one: CSharpMessenger Extended (it's implemented with static methods).

It's very strange that when I call a method directly everything is working correctly. But when I broadcast a message with the messaging system I get a NullReferenceException on some of the game objects. To my surprise adding the line if (_gameObject == null) return; solves the problem. However it's not an option to add a check if the object is null to every place where I get this exception.

What might be the problem?

Here's my code for broadcasting a message:

public class Head : MonoBehaviour {

    public Snake snake;

    void OnControllerColliderHit (ControllerColliderHit hit)
    {
        if ( hit.gameObject.GetComponent<Terrain>() )
            return;

            //This way everything was working without any surprises.
            //snake.PropCollected( hit.gameObject.GetComponent<Prop>() );
            //Using messaging system instead
        if ( hit.gameObject.GetComponent<Prop>() )
            Messenger<Prop>.Broadcast( "prop collected", hit.gameObject.GetComponent<Prop>() );
            Destroy(hit.gameObject);

        }
    }

Here's how I subscribe to the event and respond to it:

public class Snake : MonoBehaviour {

    public GameObject headBlock;

    public GameObject snakeBlocks;

    int lastSnakeBlockId;

    private GameObject FindBlockWithId( int _id )
    {
            if (!snakeBlocks) return null;    //This line somehow solves the problem; However the object is 100% assigned in the editor.

            foreach (Transform child in snakeBlocks.transform) {
                if (child.gameObject.GetComponent<SnakeBlockScript>().blockId == _id)
                {
                    return child.gameObject;
                }
            }

        return headBlock;
    }

    void Awake()
    {
        //Set up message listeners
        Messenger<Prop>.AddListener("prop collected", AddBlock);    
    }

    public void AddBlock(Prop _prop)
    {
        GameObject lastBlock = FindBlockWithId(lastSnakeBlockId - 1);
        if (!lastBlock) return;

        //Some more code
        //...
    }
}

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

古镇旧梦 2024-12-16 10:06:36

听起来好像您遇到了“snakeBlocks”在应用程序中其他地方重新初始化的情况,并且在将该引用设置为其他内容期间,该线程偶尔会发生。

类似的东西:

snakeBlocks = null;

//Do some stuff.

snakeBlocks = someNewInstanceOfGameObject;

只是一个想法。

It sounds like you have a condition where "snakeBlocks" is re-initialized somewhere else in the application, and this thread happens to hit occasionally during that reference being set to something else.

Something Like:

snakeBlocks = null;

//Do some stuff.

snakeBlocks = someNewInstanceOfGameObject;

Just a thought.

绿光 2024-12-16 10:06:36

第一个猜测是,您正在初始化多条蛇,每当其中一条蛇抓住某物时,所有蛇都会(意外地?)变长。

由于未提供 Snake 的初始化代码和构造函数,因此我最好建议您将 SnakeBlocks 初始化为相当于空集合而不是 null。

或者您不会创建不会立即发挥作用的 Snake 对象。

First guess is that you're initializing multiple snakes, all of which are (accidentally?) getting lengthened whenever one of them catches something.

Since that init code and the constructor for Snake were not provided, I can't do much better than suggest that you initialize snakeBlocks to the equivalent of an empty collection rather than null.

Or that you don't create Snake objects that are not immediately going into play.

怂人 2024-12-16 10:06:36

我注意到,在您注释掉的代码中,您说有效,您将 Prop 传递给 Snake 的 PropCollected 方法,而在您说不起作用的代码中,您将其传递给 Snake 类的 AddBlock 方法。也许这是你的错误,与消息系统无关?

I note that, in the code you commented out that you say works, you are passing the Prop to the PropCollected method of Snake whereas, in the code you say does not work, you are passing it to the Snake class's AddBlock method. Perhaps this is your bug and it has nothing to do with the messaging system?

一身骄傲 2024-12-16 10:06:36

我不是统一专家,但如果您搜索“MonoBehaviour NullReferenceException”,您会发现许多文章似乎表明这与 UnityMonoBehavior 类。

我相信您正在尝试在 Unity 真正创建一个类之前访问该类。尝试将所有代码直接或间接移至 Start() 而不是 Awake() 中。

I'm not an unity expert, but if you google around "MonoBehaviour NullReferenceException", you will find a number of articles that seem to indicate this is related to Unity and the MonoBehavior class.

I believe you're trying to access a class before it is really created by Unity. Try to move all the code into Start() instead of Awake(), directly or indirectly.

七月上 2024-12-16 10:06:36

您可能会遇到竞争条件,因为您两次获取 GetComponent,一次是为了检查 null,一次是为了实际广播消息。这意味着如果该对象在两个 getter 之间被删除,您可能会广播 null。我建议您将单个获取存储在临时变量中,并对临时变量进行空检查和广播。有道理吗?

You may have a race condition because you fetch the GetComponent twice, once to check for null and once to actually broadcast the message. That means if the object is removed between the two getters, you could be broadcasting null. I recommend you store a single get in a temporary and do the null check and the broadcast on the temporary variable. Make sense?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文