Course contentsShow
← Unity Game Development
Lesson 325 of 8285. UI and Audio SystemsFree lesson

Optimizing Data Flow with Observable Patterns

Learners will implement the observer pattern to notify UI elements of state changes efficiently without requiring constant polling in the Update loop.

In this lesson, you will learn how to replace expensive Update loop polling with the Observer pattern to keep your UI perfectly synced with your game data.

The Problem with Polling

Beginners often check for data changes by placing code inside the Update() method, like checking if (health != lastHealth) { updateUI(); } every single frame. This is inefficient; your CPU spends precious cycles asking, "Has anything changed?" hundreds of times per second, even when the answer is "no."

The Observer Solution

The Observer pattern flips this script: instead of the UI "asking" the data for updates, the data "tells" the UI when something significant happens. We achieve this by creating a property that triggers a notification only when its value actually changes.

Consider this simple Observable<T> pattern:

public class Observable<T>
{
    private T _value;
    public event System.Action<T> OnValueChanged;

    public T Value
    {
        get => _value;
        set
        {
            if (!EqualityComparer<T>.Default.Equals(_value, value))
            {
                _value = value;
                OnValueChanged?.Invoke(_value); // Only notify when changed
            }
        }
    }
}

Implementing in your UI

In your Game Manager, you hold the data: public Observable<int> PlayerHealth = new Observable<int>();

In your UI Controller script, you "subscribe" to that data just once, usually in OnEnable():

void OnEnable()
{
    gameManager.PlayerHealth.OnValueChanged += UpdateHealthBar;
}

void UpdateHealthBar(int newHealth)
{
    // This code only runs when PlayerHealth actually changes!
    healthLabel.text = $"HP: {newHealth}";
}

By subscribing, the UI sits idle until the Observable sends a signal. This eliminates the need for Update() polling entirely, drastically reducing the overhead on your game’s performance and keeping your UI logic cleanly decoupled from your core gameplay systems.

Key Takeaway: Use the Observer pattern to turn "polling" into "pushing," ensuring your UI only reacts when data actually changes, rather than wasting performance checking for changes every frame.