C# MessagingSystem导致NullReferenceException

C# MessagingSystem导致NullReferenceException,c#,messaging,unity3d,C#,Messaging,Unity3d,我决定在我的项目中实现一个简单的消息传递系统。我正在使用这个:(它是用静态方法实现的) 非常奇怪的是,当我直接调用一个方法时,一切都正常工作。但是,当我用消息传递系统广播消息时,在一些游戏对象上会出现NullReferenceException。令我惊讶的是,添加了一行if(_gameObject==null)返回解决了这个问题。但是,如果对象在我得到此异常的每个地方都为null,则不能添加检查 有什么问题吗 这是我广播信息的代码: public class Head : MonoBehavio

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

非常奇怪的是,当我直接调用一个方法时,一切都正常工作。但是,当我用消息传递系统广播消息时,在一些游戏对象上会出现NullReferenceException。令我惊讶的是,添加了一行
if(_gameObject==null)返回解决了这个问题。但是,如果对象在我得到此异常的每个地方都为null,则不能添加检查

有什么问题吗

这是我广播信息的代码:

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

        }
    }
公共类负责人:单一行为{
公共蛇;
控件碰撞无效(控件碰撞无效)
{
if(hit.gameObject.GetComponent())
返回;
//这样,一切都顺利进行,没有任何意外。
//snake.PropCollected(hit.gameObject.GetComponent());
//改为使用消息传递系统
if(hit.gameObject.GetComponent())
广播(“道具收集”,hit.gameObject.GetComponent());
摧毁(命中游戏对象);
}
}
以下是我订阅活动并对其作出回应的方式:

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
        //...
    }
}
公共类蛇:单一行为{
公共游戏对象头块;
公共游戏物体蛇形块;
int lastSnakeBlockId;
私有游戏对象FindBlockWithId(int\u id)
{
如果(!snakeBlocks)返回null;//这一行以某种方式解决了问题;但是该对象在编辑器中是100%赋值的。
foreach(在snakeBlocks.Transform中转换子对象){
if(child.gameObject.GetComponent().blockId==\u id)
{
返回child.gameObject;
}
}
回流头块;
}
无效唤醒()
{
//设置消息侦听器
Messenger.AddListener(“道具已收集”,AddBlock);
}
公共无效添加块(道具_道具)
{
GameObject lastBlock=FindBlockWithId(lastSnakeBlockId-1);
如果(!lastBlock)返回;
//还有代码吗
//...
}
}

谢谢大家!

第一个猜测是,您正在初始化多条蛇,当其中一条蛇抓到什么东西时,所有这些蛇(意外地?)都会变长

由于没有提供Snake的init代码和构造函数,我只能建议您将snakeBlocks初始化为空集合的等价物,而不是null


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

听起来您有一个条件,即“snakeBlocks”在应用程序中的其他地方重新初始化,并且在将引用设置为其他内容的过程中,该线程偶尔会命中

比如:

snakeBlocks = null;

//Do some stuff.

snakeBlocks = someNewInstanceOfGameObject;

只是想一想。

我注意到,在您注释掉的代码中,您说可行,您将道具传递给Snake的PropCollected方法,而在您说不可行的代码中,您将道具传递给Snake类的AddBlock方法。可能这是您的错误,与消息传递系统无关?

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

我不是unity专家,但如果你搜索“MonoBehavior NullReferenceException”,你会发现许多文章似乎表明这与
unity
MonoBehavior
类有关


我相信您正在尝试在Unity真正创建类之前访问它。尝试直接或间接地将所有代码移动到
Start
(),而不是
Awake
()。

可能重复的Does
销毁(hit.gameObject)将引用设置为null,但不可能从某个列表的某个位置删除所述引用?(可能是听众列表)我不确定您是否发布了足够的代码来说明这个问题。我们有没有办法看到更多的代码?使用公共“snakeBlocks”字段的代码可能会有所帮助。