Events & tokens
Lifecycle Recipes
Apply tokens and bags to MonoBehaviours, managers, pooled listeners, rebinding, and debug dispatch.
- MonoBehaviour
- Managers
- Pooled listeners
- Rebinding
These recipes show where tokens and bags usually belong in Unity code.
Lifecycle Recipes
Recipe: Simple MonoBehaviour Subscriber
Use this for most scene objects.
public sealed class HealthAudio : MonoBehaviour
{
private readonly AzEventTokenBag _subscriptions = new();
private void OnEnable()
{
CombatEvents.HealthChanged.Subscribe(OnHealthChanged).AddTo(_subscriptions);
}
private void OnDisable()
{
_subscriptions.DisposeAll();
}
private void OnHealthChanged(int health)
{
// Play audio.
}
}Recipe: Persistent Manager
Use this for objects that subscribe once and live for the whole scene or app lifetime.
public sealed class AnalyticsManager : MonoBehaviour
{
private readonly AzEventTokenBag _subscriptions = new();
private void Awake()
{
CombatEvents.CombatStarted.Subscribe(OnCombatStarted).AddTo(_subscriptions);
CombatEvents.DamageReported.Subscribe(OnDamageReported).AddTo(_subscriptions);
}
private void OnDestroy()
{
_subscriptions.Dispose();
}
private void OnCombatStarted()
{
}
private void OnDamageReported(in DamageReport report)
{
}
}Recipe: Temporarily Muting One Listener
private AzEventToken _token;
private void Awake()
{
_token = CombatEvents.HealthChanged.Subscribe(OnHealthChanged);
}
public void SetMuted(bool muted)
{
if (muted)
{
_token.Pause();
}
else
{
_token.Resume();
}
}
private void OnDestroy()
{
_token.Dispose();
}Recipe: Temporarily Muting a Group
private readonly AzEventTokenBag _uiSubscriptions = new();
public void HidePanel()
{
_uiSubscriptions.PauseAll();
}
public void ShowPanel()
{
_uiSubscriptions.ResumeAll();
}Recipe: Rebinding to a Different Event Source
When an object changes the source it listens to, dispose the old source token before subscribing to the new one.
private AzEventToken _doorToken;
private Door _door;
public void Bind(Door door)
{
_doorToken.Dispose();
_door = door;
_doorToken = _door.Opened.Subscribe(OnDoorOpened);
}
private void OnDestroy()
{
_doorToken.Dispose();
}Recipe: Instance Event Producer and Consumer
public sealed class Door : MonoBehaviour
{
public readonly AzEvent Opened = new();
public void Open()
{
Opened.Invoke();
}
}
public sealed class DoorLight : MonoBehaviour
{
[SerializeField] private Door _door;
private AzEventToken _token;
private void OnEnable()
{
if (_door != null)
{
_token = _door.Opened.Subscribe(OnDoorOpened);
}
}
private void OnDisable()
{
_token.Dispose();
_token = AzEventToken.Invalid;
}
private void OnDoorOpened()
{
// Turn on the light.
}
}Recipe: Safe Debug Dispatch
AzInvokeResult result = CombatEvents.DamageReported.InvokeSafe(in report);
if (result.Exceptions > 0)
{
Debug.LogWarning(
$"DamageReported invoked {result.Invoked} handlers with {result.Exceptions} exception(s). " +
$"First: {result.FirstException?.Message}");
}