TabletopKit
Build visionOS board games whose synchronized state changes flow through TabletopAction and render with RealityKit. The availability matrix below owns version details.
Contents
Workflow
- Confirm visionOS availability, TabletopKit capability, and whether the experience needs local, shared, or SharePlay-backed play.
- Model stable identifiers, seats, equipment, and table geometry before rendering entities.
- Express state changes as tabletop actions with validation, turn ownership, and deterministic outcomes.
- Connect interactions and RealityKit representations without making rendered entities the source of truth.
- Verify reset, reconnect, late-join, undo, and multi-participant behavior.
Route by Task
- Read core implementation details for setup, tables, equipment, seats, actions, interactions, RealityKit rendering, and Group Activities wiring.
- Read extended TabletopKit patterns for custom actions, dice simulation, card layouts, state bookmarks, observers, and network coordination.
Core Decisions
- Keep game state and equipment identifiers deterministic across participants.
- Validate custom actions before mutation and keep turn/seat authority explicit.
- Use TabletopKit interactions for tabletop semantics; use RealityKit for presentation and effects.
- Treat SharePlay transport, reconnection, and late joining as lifecycle states, not happy-path callbacks.
Common Mistakes
- Skipping seat claim. Players must call
claimAnySeat()orclaimSeat(_:)before interacting with equipment. Without a seat, actions are rejected. - Mutating state outside actions. All state changes must go through
TabletopActionorCustomAction. Directly modifying equipment properties bypasses synchronization. - Missing custom action registration. Register every custom action with
setup.register(action:)before use. - Not handling action rollback. Actions are optimistically applied and can be
rolled back if validation fails on the arbiter. Implement
actionWasRolledBack(_:snapshot:)to revert UI state. - Ignoring discarded actions when available. Implement
actionWasDiscarded(_:)when local action queue pressure matters; it is called for local actions that cannot be enqueued. - Using wrong parent ID. Equipment
parentIDin state must reference a valid equipment ID (typically the table or a container). An invalid parent causes the piece to disappear. - Ignoring TossOutcome faces. After a toss, read the face from
outcome.tossableRepresentation.face(for: outcome.restingOrientation)rather than generating a random value. The physics simulation determines the result. - Testing multiplayer in Simulator. Group Activities do not work in Simulator. Multiplayer requires physical Apple Vision Pro devices on a FaceTime call.
Review Checklist
- The centralized platform/availability matrix is applied
-
TableSetupcreated with aTabletop/EntityTabletopconforming type - All equipment conforms to
EquipmentorEntityEquipmentwith correct state type - Seats added and
claimAnySeat()/claimSeat(_:)called at game start - All custom actions registered with
setup.register(action:) -
TabletopGame.Observerreconciles confirmed, rolled-back, discarded, and bookmark-reset outcomes with the current snapshot -
EntityRenderDelegateorRenderDelegateconnected -
.tabletopGame(_:parent:automaticUpdate:)modifier onRealityView -
GroupActivitydefined andcoordinateWithSession(_:)called; multiplayer described as Group Activities/SharePlay synchronization - Group Activities capability added in Xcode for multiplayer builds
- Debug visualization (
debugDraw) disabled before release - Device notes state Simulator is single-player only; multiplayer requires 2+ Apple Vision Pro units on FaceTime
References
- TabletopKit patterns -- extended patterns for observer implementation, custom actions, dice simulation, and card overlap
- TabletopKit networking and state -- multiplayer GroupActivities coordination, bookmarks, undo, and debugging
- Apple Documentation: TabletopKit, Creating tabletop games, Synchronizing group gameplay
- Simulating dice rolls, Implementing playing card overlap
- WWDC24 session 10091: Build a spatial board game
- Core implementation details -- setup, API wiring, and focused implementation recipes moved out of the entrypoint.