Got a question about delegates.
In my game, I’m using a List to keep track of a list of methods to call when an enemy is destroyed. It’s a one time notification that will go to 0-3 other components in either the same GameObject or components in other GameObjects, depending on the type of enemy and the context. I use object pooling for the enemies, so I need to be able to easily clean up the list when an enemy is despawned.
There are various scenarios that have different notification requirements. For instance, an enemy spawned as part of a mission needs to tell the mission class that it’s dead, what wave it’s part of, and whether it’s dead or just disabled. The mission class can decrement a counter for a particular enemy wave to determine completion of mission objectives, etc. There are a few other scenarios that are probably too detailed to get into.
So far it’s working fine. I’m just wondering if there’s a better way to go here.
What I’ve tried and rejected (and why):
UnityEvent - can’t pass args, so that’s out
Traditional C# delegate events - worked well with the traditional technique of subscribing to an event, like:
newFighter.OnShipNeutralized += _mission.OnShipNeutralized;
But my concern is that since the enemy GameObjects are pooled, I’d need to clean up the subscriptions when the enemy is despawned. Yeah, you can do -=, but you have to have references to all that stuff, which I don’t. There are ways of cleaning those up, but they’re ugly. It seems that event subscriptions are better suited for events that are going to be fired more than once and that aren’t tied to pooled objects.
BroadcastMessage - shouldn’t have to say much here. I went to the dark side shortly, since this worked for components within the same GameObject and was easy, but the main downside is that it simply wasn’t flexible enough.
So I ended up putting a public field on my main enemy class that other classes can add their methods to, like:
newFighter.ShipIsNeutralizedDelegateList.Add(_mission.OnShipNeutralized);
Then when the enemy is dead, the enemy class does this:
for (int i = 0; i < ShipIsNeutralizedDelegateList.Count; i++)
{
ShipIsNeutralizedDelegateList[i].Invoke(new ShipEventArgs(GroupName, false));
}
// Now clear the list
ShipIsNeutralizedDelegateList.Clear();
The downside for general use is that you have to wait for those methods to finish, but in my case, I’m not doing much in those, and besides, the enemy is dead at that point anyway, so there’s no particular rush.
Any thoughts on a better approach? What I have is working for what I need, but I’m curious.