How TEngine Automatically Cleans Up Events When UI Is Destroyed
TEngine automatically removes UI event listeners by storing them in a GameEventMgr instance that clears all registered delegates when the UIBase class receives Unity's OnDestroy callback.
The alex-rachel/tengine framework eliminates manual event unsubscription in Unity UI development through an automated lifecycle management system. By coupling each UI component with a dedicated GameEventMgr instance, TEngine ensures that automatically clean up events when UI is destroyed happens without developer intervention, preventing memory leaks and null reference exceptions.
The Architecture Behind Automatic Event Cleanup
GameEventMgr: The Central Registry
Located at UnityProject/Assets/TEngine/Runtime/Core/GameEvent/GameEventMgr.cs, the GameEventMgr class implements IMemory and maintains two parallel collections to track registrations:
_listEventTypes: AList<int>storing integer event identifiers_listHandles: AList<Delegate>storing the corresponding handler references
When AddEvent() is called, the method registers the listener with the global GameEvent dispatcher and records the pairing internally via AddEventImp(). This dual-tracking enables bulk cleanup later.
UIBase: The Lifecycle Bridge
The UIBase class at UnityProject/Assets/TEngine/Runtime/Module/UILifecycle/UIBase.cs provides the critical link between Unity's destruction phase and TEngine's cleanup logic. Every UI component inherits a protected _eventMgr field initialized to new GameEventMgr().
The base class overrides OnDestroy() to invoke _eventMgr.Clear(), ensuring that automatically clean up events when UI is destroyed occurs precisely when the GameObject is destroyed.
Step-by-Step Cleanup Process
-
Event Registration: When a UI script calls
AddUIEvent(eventType, handler), the base class forwards this to_eventMgr.AddEvent(). This registers withGameEvent.AddEventListener()and stores the mapping in_listEventTypesand_listHandles. -
Destruction Trigger: Unity calls
MonoBehaviour.OnDestroy()when the UI GameObject is destroyed. -
Cleanup Invocation: The
UIBase.OnDestroy()override executes_eventMgr.Clear(). -
Listener Removal: The
Clear()method iterates through all stored pairs and unregisters them:for (int i = 0; i < _listEventTypes.Count; ++i) { var eventType = _listEventTypes[i]; var handle = _listHandles[i]; GameEvent.RemoveEventListener(eventType, handle); } -
Reference Release: After unregistering from the global dispatcher,
_listEventTypes.Clear()and_listHandles.Clear()remove all references, allowing the garbage collector to reclaim the UI object's memory.
Practical Implementation Example
using UnityEngine;
using System;
public class InventoryPanel : UIBase
{
private const int UpdateInventoryEvent = 2001;
private void Start()
{
// Register event - no manual cleanup needed
AddUIEvent(UpdateInventoryEvent, RefreshInventory);
}
private void RefreshInventory()
{
Debug.Log("Refreshing inventory display");
}
// Cleanup happens automatically in UIBase.OnDestroy()
}
This pattern applies to any class inheriting from UIBase. The framework handles the entire lifecycle, allowing developers to focus on business logic rather than subscription management.
Memory Safety Benefits
The automatically clean up events when UI is destroyed mechanism prevents two common Unity pitfalls:
- Memory leaks: Stale delegate references keep destroyed UI objects alive in the global
GameEventdispatcher - Null reference exceptions: Callbacks firing on destroyed MonoBehaviours after scene transitions
By encapsulating the cleanup in GameEventMgr.Clear() and triggering it through UIBase.OnDestroy(), TEngine guarantees that no dangling callbacks remain when UI objects are destroyed.
Summary
- TEngine stores UI event registrations in the
GameEventMgrclass located atUnityProject/Assets/TEngine/Runtime/Core/GameEvent/GameEventMgr.cs - The
UIBaseclass atUnityProject/Assets/TEngine/Runtime/Module/UILifecycle/UIBase.csprovides automatic cleanup by calling_eventMgr.Clear()in itsOnDestroy()override Clear()iterates through_listEventTypesand_listHandlesto callGameEvent.RemoveEventListener()for every registered delegate- Developers using
UIBasenever need to manually unregister events; the framework handles cleanup when Unity destroys the GameObject - This design prevents memory leaks and null reference exceptions by ensuring zero orphaned callbacks after UI destruction
Frequently Asked Questions
What triggers the automatic cleanup in TEngine?
Unity's OnDestroy lifecycle method triggers the cleanup. When a UI GameObject is destroyed, the UIBase class receives the OnDestroy callback and immediately invokes _eventMgr.Clear(), which removes all registered listeners from the global GameEvent dispatcher.
Do I need to manually unregister events in TEngine UI classes?
No. When you inherit from UIBase and use AddUIEvent() or _eventMgr.AddEvent(), the framework automatically tracks all registrations. The Clear() method in GameEventMgr.cs handles unregistration when the UI is destroyed, eliminating the need for manual cleanup code in your UI scripts.
What happens if I don't use UIBase for my UI components?
Without inheriting from UIBase, you lose the automatic cleanup mechanism. You would need to manually manage a GameEventMgr instance and ensure you call Clear() during your component's destruction phase. The base class exists specifically to provide this lifecycle management automatically.
Where is the cleanup logic located in the source code?
The cleanup implementation spans two critical files: UnityProject/Assets/TEngine/Runtime/Core/GameEvent/GameEventMgr.cs contains the Clear() method that iterates through _listEventTypes and _listHandles to call GameEvent.RemoveEventListener(), while UnityProject/Assets/TEngine/Runtime/Module/UILifecycle/UIBase.cs provides the OnDestroy() override that triggers this cleanup process.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →