KnuckleCracker / CW4-bug-tracker

The gathering point for bugs and supporting information, or suggestions about additional features.
Creative Commons Attribution Share Alike 4.0 International
13 stars 1 forks source link

Skimmers can cause null pointer exceptions when destroyed in a mverse session #924

Closed knucracker closed 3 years ago

knucracker commented 3 years ago

Skimmers can cause null pointer exceptions when destroyed in a mverse session

knucracker commented 3 years ago

The basic problem starts with Mirror (the networking library). Mirror has no way to catch an object destruction (other than OnDestroy, which happens too late) or to send a message on an object that is being destroyed. For instance you can't call a Command from an object and destroy it in the same frame... the command will never be called.

Consequently, when in an mverse session I have to defer destruction of certain units (the 'paired' units like skimmers) by 1 frame. They get marked as destroyed, go through the motions of destruction, but are not actually destroyed as game objects till one frame later. That is so they can send a message to other instances indicating their destruction. This is required so the message actually makes it out of Mirror.

The problem ended up being that the one frame delay allowed the Start() method to be called on a skimmer after it was 'destroyed'. Normally, when a skimmer is destroyed in the frame it spawns in, it never calls its Start() method because it was just destroyed. In mverse, the actual object gets destroyed 1 frame later, so Start() gets called. Start() does stuff like adding the unit to a 'units' hashtable. And that hashtable is what is enumerated each frame to update the units. So the unit is 'destroyed' and removed from the hashtable... before it is put in the hash table (since Start() happens at the end of the frame).

I have corrected the problem by checking for 'dead' at the top of the base class Start() method. If 'dead', then abort Start(). I can't stop Start() from being called, but the call will do nothing if the unit was already destroyed.