C# Event unsubscription when Object is destroyed

Hi !

I got a Game Manager class in my code.

It subscribes to a C# event that’s not static that determines when the player is dead. The player uses the same “HP” class as the enemies. I got the instance of the player object and use GetComponent() in order to subscribe to the “onDeath” event of the player instance.

I unsubscribe the “onDeath” event in the “OnDisable” function of my Game Manager class. However, in the editor, when I close the game, I got an error. It tells me that the game object reference I use to unsubscribe the event is destroyed.

I understand that my player Game Object is destroyed before my Game Manager class is disabled, but I can’t see another solution than refactoring the code so I can subscribe to a static event.

Do you have any better ideas ?

Sorry if my english is not the best :confused:

Thanks :slight_smile:

And this is in fact is some non funny joke from unity side. This is known for years and there is still no way to detect scene destruction inside ondisable. I even reported this as issue and got reply it will be considered internally, but I have no clue what is the current state.

I think there are only two ways to overcome scene destruction problem inside OnDisable. First one is to null check everything just in case and the second one is hack I have seen in unity answers to check if this.enabled == true, becuase is should be false when disabled in standard way, however it works only if object was not disabled before.

Oh that’s too bad ! :confused:
If I use a null check, I will get memory leaks because I don’t unsubscribe my event, isn’t it ?
I think I will change my code a little bit then

Thanks for the answer ! :slight_smile:

Depends on how your code works, it’s not like you must unsubscribe ever single event in your application.
For example if ComponentA subscribes to it’s own event or to event of component on the same game object then it will never create memory leak when you destroy that object, because it’s GC anyway.
Other example - when scene is destroyed there might be other object listening, but most likely it will be object from the same scene, it means they are both destroyed and there is no object to keep the reference.
Obviously removing all subscribers is good and you should do it, but if you know what you are doing you can sometimes omit reset of references or subscribers.

On top of this you null check to avoid error when application quits - special case when application exits and no one cares for memory leaks, because application is dead anyway.

2 Likes

All you need to do is check for the object being destroyed before unsubscribing, and no, there is no risk of memory leaks with this.

private SomeOtherScript publisher;

void OnEnable() {
  publisher.onDeath += DeathListener;
}

void OnDisable() {
  if (publisher != null) publisher.onDeath -= DeathListener;
}
3 Likes