Hello, I wanted to tell you very briefly about the bitter experience of using events in Unity, which led to incomprehensible errors and a ton of wasted time (good thing I guessed before solving the problem).
If you don’t want to read, then the conclusion: Unity saves event subscriptions even when restarting the scene with its objects deleted.
My application tracked the user’s intent to output using an event subscription Application.wantsToQuit +=. After calling the handler, my Save Game surface event was called, under certain conditions (it doesn’t matter which). My OnSave event was subscribed to by many of the game’s key classes, which called their function handlers that implemented the actual saving of the class’s critical data. In the wait loop that ran before letting the program close, I checked if my event OnSave != null, (wait for all signed handlers to finish) and only then proceeded to end the program or restart the scene. The code is as simple as possible:
Scene currentScene = SceneManager.GetActiveScene();
SceneManager.LoadScene(currentScene.name);
else
Application.wantsToQuit -= OnApplicationWantsToQuit;
Application.Quit();
And everything was going perfectly, when I needed certain conditions were called that led to the reaction of saving days both to closing the program and to restarting the scene. However, I ran into a big error when trying to restart the scene again (a second time) in the same game session. And of course, during the repeated restart of the scene, it seemed to me that the script in which this saving was implemented became null.
The Unity console said that I was trying to access a script that was destroyed, but the funniest thing is that physically the script was not null and the reference to it was valid, moreover, when the application closing event was triggered, the reference to the script was also not null. And here strange miracles begin, because after the reaction to the event, in the processing script itself, this same scrip became zero, although there was no reason for this and I did not change the link on it anywhere, what a delusion I thought. I completely rewrote the entire system and tried to understand why it happened exactly at the second call and why the script exists in the debugger before the reaction to the closing, and then it becomes null. The answer came to me by surprise, I thought that such a thing could not happen, but I still assumed that the event that received a subscription in the previous scene causes handlers in the new one, despite the fact that the handlers and the event in terms of game objects were completely overwritten.
And here, the most attentive will see that in the script above, there is no unsubscribe from the event when we restart the scene instead of closing the game. In short, what happens during such careless handling of events: we add a handler function to the application close event, a handler function whose object will be destroyed after the scene is reloaded, but the event will somehow keep calling the handler method, and in the subsequent firing of the same event, it will contain a reference to that handler from the previous scene, even though another one has already been created. I don’t really understand why this is happening and why resources such as events are not overwritten when the scene is overloaded, they actually belong to instances of the class that then do not exist, but it is worth noting that the class that implemented this processing did not have instances, it was executed by itself by itself, without instances, maybe because such data as references to in-memory event variables remain unchanged. Still, you need to remember that the class itself has a different allocation in the program memory than its instances, because it represents the prescribed behavior for these instances, but when I use it as if it were already an object, then they can such cases happen. I just didn’t think that unity. does not change the actual location of these things in the memory of the running game session process, so when you reload scenes you end up in the same place only with different data, and things like event Action remain with the already saved list of subscriptions. But there is another opinion, more logical, to which I am inclined, that in fact, the Applicattion events themselves are immutable during one game session, so they will keep the reference even after another scene is loaded. Haha, now I think this is not a very interesting discussion, since there is a logical explanation like what I just wrote. But in any case, maybe it will be useful to someone. Sorry for the incompetence if anything.
Therefore, to solve this problem, it was enough to simply add an unsubscribe to the event before restarting the scene.![]()
![]()