State and collections
Update UI state from C# properties, nested objects, lists, and dictionaries.
Public bridge properties expose the values your UI displays:
public int Coins { get; set; }
public string CurrentScreen { get; set; } = "MainMenu";
Assigning a state property pushes the new value to the UI. Read these values reactively in Solid; request game changes through actions.
Computed values
A computed getter such as public int Doubled => Score * 2 does not notify the
UI when Score changes. Compute display-only values in Solid instead:
const doubled = () => bridge.score * 2;
If gameplay code also needs the derived value, store it in a settable property
and update it when its inputs change. Mark public computed helpers [BridgeIgnore] to exclude them from the contract. Get-only reactive collections work differently: their
mutation methods publish updates, as described below.
Nested state
Use classes to update grouped state per field:
public sealed class PlayerState
{
public string Name { get; set; } = "";
public int Health { get; set; }
}
public PlayerState Player { get; set; } = new();
Initialize nested state before Loom starts. If Player is null at startup,
assign a PlayerState to it before changing Player.Health or Player.Name.
Snapshot collections
Arrays, List<T>, and Dictionary<K,V> are sent as whole collections. Reassign
the property to send an updated collection:
Items = new List<ItemState>(Items) { newItem };
In-place mutation does not call the property setter:
Items.Add(newItem); // Does not sync by itself.
Snapshots suit small lists or lists you replace in full, such as search results.
Texture2D, Sprite, and RenderTexture references are also supported in
state and inside collections. Render them with LoomImage; see Unity image sources.
Reactive collections
Use ReactiveList<T> or ReactiveMap<K,V> to send individual inserts, removals,
and updates:
public ReactiveList<QuestState> Quests { get; } = new();
For example, adding a quest to Quests updates the UI without sending the
entire quest list again.
UI usage
The generated TypeScript state uses camelCase names:
const bridge = useBridge();
bridge.currentScreen;
bridge.player.health;
bridge.quests;
After changing the state shape, follow Change the contract.