Prefer events over Update ownership
Snapshot
~80 sec
Prefer events over Update ownership when a component only needs to react to a change. Polling in Update hides who caused the change; an event keeps the reaction on the signal that owns the fact.
You will learn
- Contrast Update polling with an event subscription for the same invented readout.
- Name who owns the score change versus who owns the label reaction.
- Subscribe in OnEnable and unsubscribe in OnDisable so ownership stays temporary and explicit.
Target outcome
You can keep a small Unity reaction on the event that caused it instead of polling every frame.
Visual walkthrough
Visual walkthrough
~6 min
Four ownership ideas
Cause owner
The component that changes the fact (score, health, pool state).
Reaction owner
The component that updates a view or side effect when the fact changes.
Event
A named signal the cause raises when the fact changes.
Polling
Reading the fact every frame in Update without a signal of change.
Update polling versus event reaction
Approach Ownership Work when idle Debuggability Read every frame in UpdateThe readout asks the board for score continuously. The readout owns a constant question, not a reaction to a change. Work happens even when the score never changed. Harder to see which write caused a label flicker. Subscribe to ScoreChangedThe board raises an event; the readout handles only that signal. Cause and reaction stay on explicit components. Idle frames do no score work. You can breakpoint the event invoke and the handler. Cause lane versus reaction lane
Read the sequence as two owners: the board writes the fact and raises the signal; the readout only reacts while subscribed.
SignalBoard (cause)
Mutate the fact
AddScore changes the board's own score field.
score += delta;Raise the event
The board notifies subscribers without knowing who they are.
ScoreChanged?.Invoke(score);
ScoreReadout (reaction)
Subscribe
OnEnable attaches HandleScore to ScoreChanged.
board.ScoreChanged += HandleScore;Update the view
HandleScore owns only the label reaction.
label.text = value.ToString();Unsubscribe
OnDisable detaches so a disabled object stops reacting.
board.ScoreChanged -= HandleScore;
- SubscribeMutate the factwaits for
- Mutate the factRaise the eventthen
- Raise the eventUpdate the viewnotifies
- Update the viewUnsubscribeuntil disable
Read the sequence as two owners: the board writes the fact and raises the signal; the readout only reacts while subscribed. Reading order
- Subscribe
OnEnable attaches HandleScore to ScoreChanged.
board.ScoreChanged += HandleScore; - Mutate the fact
AddScore changes the board's own score field.
score += delta; - Raise the event
The board notifies subscribers without knowing who they are.
ScoreChanged?.Invoke(score); - Update the view
HandleScore owns only the label reaction.
label.text = value.ToString(); - Unsubscribe
OnDisable detaches so a disabled object stops reacting.
board.ScoreChanged -= HandleScore;
Connection explanations
- Subscribe → Mutate the fact (waits for)
The reaction must be subscribed before a score change can reach the label.
- Mutate the fact → Raise the event (then)
The cause owns both the write and the signal that announces it.
- Raise the event → Update the view (notifies)
The event carries the new score so the readout never polls in Update.
- Update the view → Unsubscribe (until disable)
Unsubscribing ends ownership of the reaction for that object's lifetime.
Keep the reaction on the signal
Invented MonoBehaviours only. The board owns the score write; the readout owns the label reaction and the subscription lifetime.
Languagecsharp public sealed class SignalBoard : MonoBehaviour { public event System.Action<int> ScoreChanged; private int score; public void AddScore(int delta) { score += delta; ScoreChanged?.Invoke(score); } } public sealed class ScoreReadout : MonoBehaviour { [SerializeField] private SignalBoard board; [SerializeField] private TMPro.TextMeshProUGUI label; private void OnEnable() { board.ScoreChanged += HandleScore; } private void OnDisable() { board.ScoreChanged -= HandleScore; } private void HandleScore(int value) { label.text = value.ToString(); } }Code annotations
Lines 3-12
Cause raises the event
AddScore mutates score, then invokes ScoreChanged with the new value.
Effect: Listeners learn about the change without polling.
Lines 19-27
Subscribe for a temporary lifetime
OnEnable attaches; OnDisable detaches so disabled objects stop reacting.
Effect: Ownership of the reaction is scoped to the active lifetime.
Lines 29-32
Reaction owns the view
HandleScore updates only the label when the event fires.
Effect: The readout never asks for score on idle frames.
Choose the reaction style
A health bar should refresh only when damage or heal is applied. Should the bar poll health in Update, or subscribe to a HealthChanged event? Why?
Expected reasoning
Subscribe to HealthChanged (or equivalent). Damage and heal are discrete facts; polling every frame hides the cause and wastes idle work. The health owner raises the event; the bar owns the view reaction and unsubscribes when disabled.