I have a grid of Box Colliders that are supposed to sense and monitor other objects in them. The OnTriggerEnter event tests to see if the “occupancy” is Null, and if it is then the block can be occupied by something else. So here is the problem: When the occupancy variable reports “None” (null) new objects occupy the spot with out any problems, but when the object that was in that spot is destroyed the variable reports as “Missing”, and reports to the Debug.Log show it as null, but it does not test as null on the OnTriggerEnter event. So my question is How do I test for a random “missing” object, or how do I clear it so it is actually null?
I do not want to bog down my app but having hundreds/thousands of these colliders testing an OnCollisionStay to force a null, nor do I want to have to traverse the object grid unnecessarily with each event call to force a null.
Destroy(block.occupancy);
block.occupancy = null;
I have no direct answer, but a workaround came to mind.
You could have your occupants reference their occupying collider, and notify the collider when it gets destroyed, thus allowing it to be occupied later by other objects.
Alternatively, depending on how fast objects are added and removed to the grid, and the size of your grid, you could have your occupants BroadcastMessage to your colliders to notify them of it’s destruction.
This could work, but it avoids the real question; getting “Missing” when you should be getting null. Someone smarter than me might be able to help with that.
Ok, maybe some code will help us, to help you, as far as i get with this i think the problem is that you’re trying to acces a GameObject that’s already been deleted (mean Null or Object reference not set to an instance of an object) if this is the case, you should put some checks like this
OnCollisionEnter(Collision occupancyObject)
{
objInHere = occupancyObject.gameObject;
}
OnCollisionStay(Collision stayingObject)
{
if(objInHere!=null && stayingObject.gameObject == objInHere)
{
//Do whatever you need to
}
else
{
objInHere = null;
}
}
Maybe this should help.
It actually doesn’t need code. When I started troubleshooting the problem I set up a null test in the collider objects Update where it first Debug.Log(ged)the Occupancy, then tested for null and simply changed the color of their associated cubes. The variable is public so I could monitor it in the inspector as well. The debug console reported both types as Null, but the inspector listed the null as none where as the destroyed object was just missing. Because the Log came before the color change test, and reported both as null but only the none version worked as I expected. I started trying to track down ways to turn missing to null with out needing the actual missing object to do it.
instead of using colliders, use compare range between the objects. its much more lighter than colliders since its not using physics. if you want to optimize it further, use on FixedUpdate.
As DriesVienne wrote, using an Observer pattern, messaging system or the like if probably your best bet to cleanly set your references to null before objects are actually destroyed.
Unity is using a trick to distinguish null and missing values, and on top of that you cannot call a method on a null/missing object, so I had to find foolish to weird workarounds. In any case you should use them for debugging purposes only:
null → outputs Null
(but an empty string if concatenated)
missing → outputs null
- string.Format(“{0}”, obj)
null → ""
missing → "null"
- bool isMissing = (obj ?? (object) “missing”).ToString() == “missing”;
null → false
missing → true
I borrowed the last one from an answer to How to do ToString for a possibly null object? but you need to create a small string, or anything you can cast to an object and then compare to distinguish from null. An alternative expression that does use strings is (obj ?? (MyClass) new MyClass()) != null
but it requires creating a temporary object of your type…
Tested on: a sub-class of EditorWindow
, to check whether my window reference was missing after I closed it.