I am creating a prototype for a game, wherein there is character say “baby superman” who is flying and on the path he would get power-ups like booster rockets, which would eventually increase his speed and fly faster. I am using C#.
Here I have used delegates & events, where OnCollisionEnter on the power up will fire up an event AddBoosterRockets and as “superbaby” has it its function attached to this event, which would show the rocket animation and the speedup. This is working fine as many times I click the play button, start/stop/restart it, there is no issues in the execution.
Now OnGUI function, I have added a “Reset” button which when clicked will load the current level i.e. via “Application.loadedLevel(0)”.
The superbaby moves as intended and as soon as it hits the power up, event is received and when I attach the rocket animation as the child of superbaby gameObject, I need to assign the transform of superbaby as the parent of the rocket animation, this where where I start getting the following error : The transform is “null”, I have no clue how this happens.
The object of type ‘C_SuperBaby’ has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
This error only occurs when I reload the via “Application.loadedLevel(0)”. This never occurs when I click the play button on the top and restart as many times I want. I did google and more frequently the topic in discussion came was - to remove any static variables from the code to avoid loosing of the reference, to avoid null reference.
I don’t know whether this error is caused by the static key word used in front of the declaration of the event. i.e.
public delegate void delegateAddBoosterRockets();
public static event delegateAddBoosterRockets AddBoosterRockets;
There are no other static keyword used other than for declaring events. I would love to use delegate & events, and I believe there might be some way to overcome this issue.
Could anyone kindly guide me at this front?
where the very first answer explains static variables as “Static variables on the other hand are not destroyed because they are part of a class, not an instance. You have to reset these manually.” So it was pretty clear that what all you assign to a static variable must be monitored mannually.
So this meant the static event variable being a part of class still hold the referce of the eventhandlers of C_SuperBaby within the AddBooosterRockets event of C_PowerUps class. As we use Class.EventName += EventHandler to add a listener, similarly we can remove the listener by Class.EventName -= EventHandler . Now when should we remove the listeners, for this please refere the order of execution of methods or processes Unity.
There you can see the OnDestroy is fired when a MonoBehaviour object is destroyed. This is what I was looking for, so added the following lines of code inside C_SuperBaby at the end.
where AddBoosterRocketsHandler is method from C_SuperBaby, and yes thats pretty much of it. Just make sure whenever you are using statics variables and assigning them reference do make sure to monitor them as well.
It’s because super baby is created on application load, and I would guess whatever is accessing super baby is not destroyed when you load the level. So when you load the level, a NEW super baby is created but whatever was accessing super baby still have a reference to the old super baby. Each time you load the level you just need to make sure everything has updated references.
Instead of using OnDestroy, I prefer to use OnEnable and OnDisable as a good practice to subscribe and unsubscribe methods to an event; following the suggestions on the tutorial in the official documentation. If you subscribe to an event but don’t unsubscribe, you’ll have memory leaks and weird behaviors in your code.
So, let’s say you have the event OnMyEvent defined in the class MyClass and you want to subscribe using the method MyMethod. In order to avoid the situation pointed out above, just do as follows:
void OnEnable() {
// Subscribe to the event
MyClass.OnMyEvent += MyMethod;
}
void OnDisable() {
// Unsubscribe to the event
MyClass.OnMyEvent -= MyMethod;
}
OnEnable and OnDisable also guarantee that the subscription is handled properly when the game enters other states as paused or unpaused, so should be the preferred way to go.