MessagingSystem throws a NullReferenceException

I decided to implement a simple messaging system in my project. I use this one: CSharpMessenger Extended (it is implemented with static methods).

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

What could be the problem?

Here is my code for broadcasting the 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, as 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 //... } } 

Thanks!

+4
source share
5 answers

It looks like you have a condition in which "snakeBlocks" is reinitialized somewhere else in the application, and this thread sometimes gets hit when this link is set by something else.

Sort of:

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

Just a thought.

+2
source

First, suppose you initialize several snakes, all of which (by chance?) Lengthen when one of them catches something.

Since this initialization code and constructor for Snake were not provided, I can do nothing better than assume that you initialize snakeBlocks with the equivalent of an empty collection, not null.

Or that you do not create snake objects that do not immediately come into play.

+1
source

I note that in the code that you commented on what you say works, you pass Prop to the PropCollected Snake method, while in the code you say doesn't work, you pass it to the AddBlock method of the Snake class. Maybe this is your mistake and it has nothing to do with the messaging system?

+1
source

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

I believe that you are trying to access the class before it is actually created by Unity. Try moving all the code to Start () instead of Awake (), directly or indirectly.

+1
source

You may have a race condition because you get GetComponent twice, once to check for null and once to actually broadcast the message. This means that if an object is deleted between two getters, you can translate zero. I recommend that you store one access in a temporary mode and perform zero checking and transmission on a temporary variable. It makes sense?

0
source

All Articles