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
//...
}
}
谢谢!
这听起来像是你有一个条件,在应用程序的其他地方重新初始化"snakeBlocks",这个线程碰巧在引用被设置为其他东西期间偶尔击中。
类似:
snakeBlocks = null;
//Do some stuff.
snakeBlocks = someNewInstanceOfGameObject;
只是一个想法。
第一个猜测是,您正在初始化多个蛇,当其中一个捕获到某些东西时,所有蛇(意外地?)都会被加长。
由于没有提供初始化代码和Snake的构造函数,我只能建议您将snakeBlocks初始化为一个空集合,而不是null。
我注意到,在你注释掉的代码中,你说有效,你将Prop传递给Snake的propcollect方法,而在你说不工作的代码中,你将它传递给Snake类的AddBlock方法。也许这是您的错误,与消息传递系统无关?
我不是统一专家,但如果你谷歌一下"MonoBehaviour NullReferenceException",你会发现许多文章似乎表明这与Unity
和MonoBehavior
类有关。
我相信你是想在Unity真正创建一个类之前访问它。尝试将所有代码直接或间接地移动到Start
()而不是Awake
()中。
您可能有一个竞争条件,因为您两次获取GetComponent,一次检查null,一次实际广播消息。这意味着如果对象在两个getter之间被删除,您可能会广播null。我建议您在临时变量中存储单个get,并对临时变量进行空检查和广播。有意义吗?