MessagingSystem causes a NullReferenceException

本文关键字:NullReferenceException causes MessagingSystem | 更新日期: 2023-09-27 18:11:05

我决定在我的项目中实现一个简单的消息传递系统。我正在使用这个: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
        //...
    }
}

谢谢!

MessagingSystem causes a NullReferenceException

这听起来像是你有一个条件,在应用程序的其他地方重新初始化"snakeBlocks",这个线程碰巧在引用被设置为其他东西期间偶尔击中。

类似:

snakeBlocks = null;
//Do some stuff.
snakeBlocks = someNewInstanceOfGameObject;

只是一个想法。

第一个猜测是,您正在初始化多个蛇,当其中一个捕获到某些东西时,所有蛇(意外地?)都会被加长。

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

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

我不是统一专家,但如果你谷歌一下"MonoBehaviour NullReferenceException",你会发现许多文章似乎表明这与UnityMonoBehavior类有关。

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

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