- Home /
Do I need to unregister events if an instance is destroyed?
Do I need to unregister my event even if the instance is destroyed? Will it get cleaned up with the object being destroyed or will there be a memory leak?
void Awake()
{
button.OnClick += ButtonClicked;
}
void OnDestroy()
{
// Is this necessary?
button.OnClick -= ButtonClicked;
}
void ButtonClicked()
{
// Do stuff
}
Answer by mattyman174 · May 14, 2014 at 04:41 AM
Yes you should unsubscribe from any events or delegates you subscribe to. Adverse effects may come from not cleaning up after yourself properly and it is good practice to keep track of these things.
I think in this instance he might not need to unsub, because once the object is destroyed and another is created, the delegate value reverts to null so you start from an empty delegate in Awake. But I agree, it's a good habit to sub/unsub that's what I always do. It also might be good sometimes to subscribe in OnEnable, and unsub in OnDisable.
Is there an advantage in subscribing/unsubscribing with OnEnable/OnDisable over Awake/Destroy?
Really depends on the functionality you want. Though you should always unsubscribe in OnDestroy anyways.
If I have a script that simply outputs a Debug line to the console via a subscription to a delegate defined in another script that is called every second for example. Subscribing to that delegate via Awake, regardless of whether or not the script is active/enabled on that GameObject, it will still output the Debug line.
On the flip side if you subscribe to the delegate in OnEnable, you can control when that script starts to receive calls from the delegate. Same is true for Destroy/OnDisable, its all about controlling how the script receives calls from the delegate.
If you want to have a play around and see for yourself, heres a small test script I wrote to help you.
DelegateScript.cs
using UnityEngine;
using System.Collections;
public delegate void OnVoidDelegate(); // Our delegate type.
public class DelegateScript : $$anonymous$$onoBehaviour {
public static OnVoidDelegate OnSimulationUpdate; // The callback for our delegate.
public float simulationTimeStep = 0.5f;
private float simulationElapsedTime = 0.0f;
protected void Update ()
{
SimulationUpdate();
}
protected void SimulationUpdate()
{
if (simulationElapsedTime >= simulationTimeStep)
{
if (OnSimulationUpdate != null) // If there are no subscribers, dont bother.
OnSimulationUpdate(); // Send out a call to our subscribers.
simulationElapsedTime = 0.0f;
}
simulationElapsedTime += 1 * Time.deltaTime;
}
}
Subscriber.cs
using UnityEngine;
using System.Collections;
public class Subscriber : $$anonymous$$onoBehaviour {
protected void Awake()
{
DelegateScript.OnSimulationUpdate += DebugOut; // Subscribe to the delegate.
}
protected void Start()
{
}
protected void OnEnable()
{
}
protected void OnDisable()
{
DelegateScript.OnSimulationUpdate -= DebugOut; // Unsubscribe from the delegate.
}
protected void OnDestroy()
{
}
protected void DebugOut()
{
Debug.Log("Test Delegate Executed. " + Time.time);
}
}
Try moving around where you subscribe and unsubscribe to the delegate and disable/enable the script at different times to see the effects you get.
Changing the frequency of the updates is as simple as sliding the public variable simulationTimeStep on your DelegateScript GameObject.