Its because youâve destroyed the GameObject with Destroy(). Unity has two environments the C# side that you write all your code in, and the c++ where unityâs data is actually managed. because they are two separate environments, Destroying an object doesnât happen immediately. the gameobject youâve âdestroyedâ was only flagged to be destroyed and its memory is waiting to be released on the c++ side.
on the Unity side the object is represented as a fake null object so when you try to access built-in properties on the object unity will respond back that the object was (flagged) destroyed but youâre still trying to access it. Shoot() may still appear to work but the object itself is just waiting in line in the afterlife.
this is just a basic rule, but try and check if the object is null before trying to use it (and return instantly if it is)
This. The C++/C# interface is a strange place. On the C++ side, memory is unmanaged. As soon as you call destroy, the C++ object is banished into oblivion. On the C# side memory is managed. You canât banish an object to oblivion. As long as you have a reference to an object, it hangs around in memory. Itâs only if you remove all references that the GC kicks in and actually removes the object.
Using a null check is a good way to avoid this. I would go one step further and use the implicit book operator. This doesnât rely on âfake nullâ and so is less likely to cause you weird bugs in the future.
Okay, this was the problem, although I thought I had accounted for it. I was anticipating the object to be delay-destroyed but was referencing its replacement.
So by my thinking, the old turretObject was scheduled to be removed but there was a shiny new turretObject replacing it. Turns out it doesnât work that way. For whatever reason the script reference was to the old object. Using DestroyImmediate(turretObject); works and proved the fault, and I can restructure my removal earlier.