Eonevolve Learning
Unity and DevelopmentUnity and codeBeginner~6 min

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

  1. 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.

  2. Update polling versus event reaction

    ApproachOwnershipWork when idleDebuggability
    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.
  3. 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)

    1. Mutate the fact

      AddScore changes the board's own score field.

      score += delta;
    2. Raise the event

      The board notifies subscribers without knowing who they are.

      ScoreChanged?.Invoke(score);

    ScoreReadout (reaction)

    1. Subscribe

      OnEnable attaches HandleScore to ScoreChanged.

      board.ScoreChanged += HandleScore;
    2. Update the view

      HandleScore owns only the label reaction.

      label.text = value.ToString();
    3. 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

    1. Subscribe

      OnEnable attaches HandleScore to ScoreChanged.

      board.ScoreChanged += HandleScore;
    2. Mutate the fact

      AddScore changes the board's own score field.

      score += delta;
    3. Raise the event

      The board notifies subscribers without knowing who they are.

      ScoreChanged?.Invoke(score);
    4. Update the view

      HandleScore owns only the label reaction.

      label.text = value.ToString();
    5. Unsubscribe

      OnDisable detaches so a disabled object stops reacting.

      board.ScoreChanged -= HandleScore;

    Connection explanations

    1. Subscribe → Mutate the fact (waits for)

      The reaction must be subscribed before a score change can reach the label.

    2. Mutate the fact → Raise the event (then)

      The cause owns both the write and the signal that announces it.

    3. Raise the event → Update the view (notifies)

      The event carries the new score so the readout never polls in Update.

    4. Update the view → Unsubscribe (until disable)

      Unsubscribing ends ownership of the reaction for that object's lifetime.

  4. 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

    1. 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.

    2. 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.

    3. 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.

  5. 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.

Interactive flow

Play the subscription lifetime

Step through the same SignalBoard and ScoreReadout from the code above, one ownership beat at a time.

Beat 1 of 5 · waits for
  • SubscribeCause mutates the factwaits for
  • Cause mutates the factEvent firesinvokes
  • Event firesReaction owns the viewnotifies
  • Reaction owns the viewUnsubscribeuntil