Chaparral Village: Building an immersive visionOS adventure game
At a glance
| Item | Summary |
|---|---|
| Purpose | Create an adventure game using SwiftUI, RealityKit, and Reality Composer Pro 3. |
| App architecture | ChaparralVillageApp composes WindowGroup + volumetric window + ImmersiveSpace around ContentView; AppState holds shared experience state and RealityKit components and systems own per-entity behavior. |
| Main patterns | SwiftUI scene composition, SwiftUI–RealityKit bridge, Explicit immersive-space lifecycle, Observable state owner, Entity-component-system, Provider session boundary |
| Project style | Code-rich sample with 92 scanned Swift file(s) and 13721 Swift line(s); resources and generated assets are excluded from those counts. |
Project structure
Source bundle/
├── ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ChaparralVillageApp.swift # ChaparralVillageApp, PluginHandler
├── ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ContentView.swift # ContentView, ChaparralVillageRealityView
├── ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/LevelManager.swift # LevelManager, LoadSlotData, LevelLoadedEvent
├── ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/InputManager.swift # DragInput, InputManager, EventStateStatus
├── ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/AppState.swift # AppPhase, AppState
├── ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/EcsAbstractions/SceneBound.swift # SceneBound, SceneBoundTracker
├── ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/LevelMarkup/ForceContainer.swift # ForceContainer, PhysicsUpdateBehavior, ForceContainerReset
├── ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/InputProtocols.swift # TapHandler, DragEvent, DragHandler
└── ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage.realitycomposerpro/Assets/Audio/Ambient Audio/VillageAtmosphere.tm_audio_file # authored RealityKit content
Structure observations
- The runtime boundary is WindowGroup + volumetric window + ImmersiveSpace; the pruned tree lists only files that explain lifecycle, state, or framework integration.
- App code is split into role-named views, models, managers, providers, components, or systems.
- Authored
.realityor Reality Composer Pro content is a real implementation boundary; Swift loads or drives it rather than reproducing its entity graph. - This source came from Apple’s Apple-Account-gated DMG, ingested read-only after the user authenticated; it is not a public DocC ZIP.
- Apple publishes no checksum for that DMG. The SHA-256 here is the locally computed immutable identity of the authenticated download, not an Apple-published checksum.
Overall architecture
flowchart LR
ChaparralVillageApp_1["ChaparralVillageApp"]
WindowGroup___volumetric_window___ImmersiveSpace_2["WindowGroup + volumetric window + ImmersiveSpace"]
ContentView_3["ContentView"]
AppState_4["AppState"]
RealityView_entity_graph_5["RealityView entity graph"]
RealityKit_components_and_systems_6["RealityKit components and systems"]
ChaparralVillageApp_1 --> WindowGroup___volumetric_window___ImmersiveSpace_2
WindowGroup___volumetric_window___ImmersiveSpace_2 --> ContentView_3
ContentView_3 --> AppState_4
AppState_4 --> RealityView_entity_graph_5
RealityView_entity_graph_5 --> RealityKit_components_and_systems_6
Reference code
ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ChaparralVillageApp.swift:16 — the app or executable entry declares the outer scene lifecycle.
struct ChaparralVillageApp: App {
// ...
}The diagram is a responsibility flow, not a claim that every adjacent node directly calls the next. It keeps scene ownership, shared state, RealityKit content, and framework-provider work at separate levels.
Ownership and state
classDiagram
ChaparralVillageApp *-- AppState : appState
ChaparralVillageApp *-- SaveManager : saveManager
CauldronWaterDisplay --> Entity : cauldron
ContentView --> SaveManager : saveManager
Ownership evidence
ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ChaparralVillageApp.swift:18 — representative stored state or the nearest verified lifecycle anchor.
@State private var appState = AppState()
@Environment(\.physicalMetrics) var physicalMetrics
init() {
RCPCustomComponentsPlugin
.create()
.setup(context: PluginHandler())
}| Owner | Object or state | Relationship | Mutation authority |
|---|---|---|---|
ChaparralVillageApp |
AppState as appState |
creates and retains | Only the declaring scope writes |
ChaparralVillageApp |
SaveManager as saveManager |
creates and retains | The owning type coordinates writes |
CauldronWaterDisplay |
Entity as cauldron |
stores and coordinates | The owning type coordinates writes |
ContentView |
SaveManager as saveManager |
stores and coordinates | The owning type coordinates writes |
Ownership here is deliberately narrow: @Environment and weak references are shared links, initialized @State or stored services are lifecycle ownership, and a RealityView content closure owns additions to its entity graph without making the SwiftUI view a reference-type owner.
Class and protocol design
| Type | Responsibility | Depends on or conforms to |
|---|---|---|
ChaparralVillageApp (ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ChaparralVillageApp.swift:16) |
Declares app scenes and top-level dependency lifetime. | App |
ContentView (ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ContentView.swift:15) |
Presents UI and forwards gestures or lifecycle events. | View |
AppState (ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/AppState.swift:31) |
Owns observable feature state and domain transitions. | SceneBound |
SceneBound (ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/EcsAbstractions/SceneBound.swift:16) |
Declares a replaceable capability or lifecycle contract. | Identifiable, Component |
PhysicsUpdateBehavior (ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/LevelMarkup/ForceContainer.swift:19) |
Declares a replaceable capability or lifecycle contract. | Concrete framework collaborators |
TapHandler (ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/InputProtocols.swift:12) |
Declares a replaceable capability or lifecycle contract. | Identifiable |
DragHandler (ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/InputProtocols.swift:33) |
Declares a replaceable capability or lifecycle contract. | Identifiable |
Verified protocol-oriented seams: BuoyancySim → PhysicsUpdateBehavior, CutsceneManager → SceneBound, ZoneCutsceneHandler → ZoneChangeHandler, DebugDraw → SceneBound, InputProxyManager → SceneBound, ARManager → SceneBound. Framework conformances remain adapters, not proof of an app-wide protocol architecture.
Access control
| Symbol | Access | Verified effect | Likely rationale |
|---|---|---|---|
@State private var appState = AppState() (ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ChaparralVillageApp.swift:18) |
private |
Use is restricted to the declaration and same-file extensions permitted by Swift. | Inference: Hide implementation details and lifecycle-sensitive state. |
public static let dependencies: [SystemDependency] = [.after(ForceConta... (ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Alchemy/BuoyantObject.swift:32) |
public |
The declaration is available to importing modules, subject to its containing type’s visibility. | Inference: Export the type across the package-module boundary. |
No reviewed declaration uses fileprivate, private(set), open; unmodified Swift declarations are internal.
Reference code
ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ChaparralVillageApp.swift:18 — representative visibility boundary.
@main
struct ChaparralVillageApp: App {
// ...
@State private var appState = AppState()
// ...
}Logic ownership and placement
| Logic | Owning type or file | Placement rationale |
|---|---|---|
| Scene declaration and dependency lifetime | ChaparralVillageApp |
The App/entry boundary determines window, volume, and immersive-space lifetime. |
| Presentation, attachments, and gestures | ContentView |
SwiftUI view code forwards user intent and RealityView lifecycle events. |
| Shared feature state and commands | AppState |
A role-named owner prevents sibling views from duplicating transitions. |
| Tracking authorization and update streams | ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/ARManager.swift:18 |
Provider lifetime and async updates remain outside render-only view code. |
| Per-frame entity behavior | ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Alchemy/BuoyantObject.swift:31 |
RealityKit systems query component data instead of centralizing every entity update in SwiftUI. |
| Authored game behavior | ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/LevelManager.swift:182 plus Reality Composer Pro content |
Script Graph owns authored rules; Swift bridges UI and runtime events. |
Design patterns
| Pattern | Source evidence | Purpose or tradeoff |
|---|---|---|
| SwiftUI scene composition | ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ChaparralVillageApp.swift:16 |
Keeps windows, volumes, and immersive-space lifecycle visible at the app boundary. |
| SwiftUI–RealityKit bridge | ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ContentView.swift:94 |
Builds and updates a RealityKit entity graph from SwiftUI lifecycle closures. |
| Explicit immersive-space lifecycle | ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ChaparralVillageApp.swift:36 |
Makes immersive presentation a scene transition rather than hidden global state. |
| Observable state owner | ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/AppState.swift:31 |
Shares feature state across multiple views without moving framework resources into view values. |
| Entity-component-system | ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Alchemy/BuoyantObject.swift:31 |
Stores per-entity data in components and advances behavior in registered RealityKit systems. |
| Provider session boundary | ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/ARManager.swift:80 |
Owns provider lifetime separately from the SwiftUI view tree. |
Naming conventions
- Role suffixes are evidence, not decoration: App:
ChaparralVillageApp; Model:DialogModel,LadderModel; Controller:DioramaViewController; Manager:ARManager,AudioManager,CutsceneManager,InputManager,InputProxyManager. - ECS names pair data and behavior: components
BuoyantObject,Cauldron,CauldronWaterDisplay,CurtainPinComponent; systemsBuoyantObjectSystem,StirringSystem,CauldronWaterDisplaySystem,CurtainClothBodySystem. - Protocols:
SceneBound,PhysicsUpdateBehavior,TapHandler,DragHandler,Affordance,CustomRestore. - Commands use verb-led methods:
registerComponent,registerAction,registerSystem,store,load,fadeInRestoredEntities,fadeOutExistingLevel,unload. - Files generally match their primary type;
Views,Models,Managers,Providers,Components,Systems, andPackagesfolders describe architectural roles where present.
Architecture takeaways
- Treat
ChaparralVillageAppas the owner of scene declarations, not as the owner of every RealityKit entity created later. - Keep view-local interaction in SwiftUI, but move provider sessions, playback resources, shared game state, or transport state into a stable owner when their lifetime exceeds one render pass.
- Run ARKit providers for the scene lifetime and consume their asynchronous updates in cancellable tasks; map anchors to entities at the boundary.
- Use RealityKit components for per-entity data and systems for repeated simulation instead of a monolithic view model.
- Model immersive-space open, transition, and close states explicitly so windows and immersive content cannot drift apart.
Source map
| Source file | Relevant symbols |
|---|---|
ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ChaparralVillageApp.swift:16 |
ChaparralVillageApp, PluginHandler |
ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/ChaparralVillage/ContentView.swift:15 |
ContentView, ChaparralVillageRealityView |
ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/LevelManager.swift:13 |
LevelManager, LoadSlotData, LevelLoadedEvent, Level, CodingKeys, LevelLoadSlot |
ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/InputManager.swift:14 |
DragInput, InputManager, EventStateStatus, EventState |
ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/AppState.swift:14 |
AppPhase, AppState |
ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/EcsAbstractions/SceneBound.swift:16 |
SceneBound, SceneBoundTracker |
ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/LevelMarkup/ForceContainer.swift:12 |
ForceContainer, PhysicsUpdateBehavior, ForceContainerReset, ForceContainerApply |
ChaparralVillageBuildingAnImmersiveVisionOSAdventureGame/Packages/RCPCustomComponents/Sources/RCPCustomComponents/Managers/InputProtocols.swift:12 |
TapHandler, DragEvent, DragHandler, HandlesInput, InputProxy, InputAction |
- Official Apple documentation
- Provenance note: Apple-Account-authenticated DMG, ingested locally read-only; SHA-256 computed locally because Apple does not publish one for this download.