Observable<T> and Event<T>
Observable<T>, ObservableList<T>, and Event<T> are the three runtime
types that make up a bridge surface.
Observable<T>
A reactive cell. Get and set .Value; the bridge serialises and pushes to
the UI on every change.
[BridgeState] public Observable<int> Score { get; } = new(0);
// somewhere in your game logic:Score.Value = 100; // triggers a state pushint now = Score.Value; // read backObservable<T> is also subscribable from C# if you need engine-side
reactivity (e.g., updating a debug HUD):
Score.Changed += (newValue, oldValue) => { Debug.Log($"score went {oldValue} → {newValue}");};The Changed event fires after .Value is set, on the same thread that set
it. It does not fire if the new value is Equals() to the old one.
ObservableList<T>
A reactive list. Supports the usual Add, Remove, Insert, Clear,
this[int] indexer, plus a Changed event with item-level granularity.
[BridgeState] public ObservableList<string> Messages { get; } = new();
Messages.Add("hello");Messages[0] = "hi";The UI sees a typed array; fine-grained changes don’t re-render the whole list (Solid’s signal model handles this efficiently when the UI is written against the underlying signal).
Event<TPayload>
A one-shot fan-out. C# fires with a payload; the UI receives a typed callback.
[BridgeEvent] public Event<DamageEvent> Damaged { get; } = new();
Damaged.Fire(new DamageEvent { Amount = 10 });onEvent('damaged', (e) => { flashRed(e.amount)})Events do not buffer. If the UI is not yet connected (e.g. boot phase), fired events are dropped. If your engine fires an event before the UI is up, either delay the fire or use a state field instead.
Threading
All three types are designed for the main thread. Pushing state from a
background thread is undefined behaviour. If you need to update state from
a worker, UnityMainThreadDispatcher.Enqueue(...) (or your engine’s
equivalent) to the main thread first.