Two components handle in-game scoring: Score (data + events) and Scoreboard (DOM overlay that renders the data). Use them together or just Score if you're rendering UI elsewhere.
Score
A score tracker keyed by player ID. The Score component is typically attached to a world-level entity rather than per-player — it tracks all players' scores in one place.
JSON
A common pattern: a top-level "World" entity owns the Score component.
Driving the score from gameplay
When a player picks up a coin, kills an enemy, scores a goal — emit score.add:
The Score System updates its internal map and emits score.changed with the new value. Subscribe to score.changed in your UI / sound / particle systems if you want effects when scores update.
Scoreboard
A DOM overlay that renders the current Score state. It creates a <div> outside the canvas, positioned by CSS, and re-renders whenever score.changed fires.
JSON
The Scoreboard listens for score.changed on the EventBus and re-renders only the affected player's row. It's lightweight DOM work — fine to run alongside your 60fps game loop.
Custom styling
The Scoreboard renders inline styles. To restyle, pass an explicit style field or replace the component with your own Solid/React/whatever UI that subscribes to score.changed.
The component is just an event listener + DOM writer — you can absolutely build your own HUD that subscribes to the same events without using Scoreboard at all.
Common patterns
Game over on threshold
Persisting score across scene loads
Save the score state when transitioning out:
And restore by passing it in via the scene JSON or directly setting it after instantiation.
Multi-team scoring
Don't fight the API — give each team its own player ID:
And tag entities 'team-red' or 'team-blue' so your gameplay Systems know who scored for whom.
Where to next
- Animation & Mesh —
.glbloading and skeletal animation - Extending — viz panels, custom registries