Animating entity rotation with a system
At a glance
| Item | Summary |
|---|---|
| Purpose | Rotate an entity around an axis using a Component and a System. |
| App architecture | RotationApp loads the scene in ContentView; RotationComponent stores per-entity speed and RotationSystem queries those components to update transforms each frame. |
| Main patterns | SwiftUI scene composition, UI–RealityKit bridge, Entity-component-system, Component-system update loop |
| Project style | Code-light sample with 8 scanned Swift file(s) and 248 implementation line(s). |
Project structure
Source bundle/
├── Packages/SceneAssets/Sources/SceneAssets/RotationSystem.swift # RotationSystem
├── Packages/SceneAssets/Sources/SceneAssets/RotationComponent.swift # RotationComponent
├── Rotation/RotationApp.swift # RotationApp
├── Rotation/ContentView.swift # ContentView
├── Packages/SceneAssets/Sources/SceneAssets/RotationAxis.swift # RotationAxis
├── Packages/SceneAssets/Sources/SceneAssets/SceneAssets.swift
└── Packages/SceneAssets/Package.realitycomposerpro/ProjectData/main.json # authored RealityKit content
Structure observations
- The runtime boundary is WindowGroup; the tree is pruned to lifecycle, state, framework, rendering, and ECS files.
- The source is Swift; its compact size does not erase any explicit owner shown below.
- Authored
.reality,.rkassets, or Reality Composer Pro content is an implementation boundary; Swift loads or drives it rather than reproducing its entity graph.
Overall architecture
flowchart LR
RotationApp_1["RotationApp"]
WindowGroup_2["WindowGroup"]
ContentView_3["ContentView"]
RotationSystem_4["RotationSystem"]
RealityKit_entity_graph_5["RealityKit entity graph"]
RealityKit_components_and_systems_6["RealityKit components and systems"]
RotationApp_1 --> WindowGroup_2
WindowGroup_2 --> ContentView_3
ContentView_3 --> RotationSystem_4
RotationSystem_4 --> RealityKit_entity_graph_5
RealityKit_entity_graph_5 --> RealityKit_components_and_systems_6
Reference code
Rotation/RotationApp.swift:12 — executable or app-lifecycle anchor.
struct RotationApp: App {
// ...
}The diagram is a responsibility flow, not a claim that every adjacent node directly calls the next. It separates lifecycle, presentation, stable state, framework/session work, and the RealityKit entity graph.
Ownership and state
classDiagram
ContentView *-- Entity : telescope
ContentView *-- RotationAxis : axis
RotationSystem *-- EntityQuery : rotationQuery
ContentView *-- Bool : isRotating
Ownership evidence
Rotation/ContentView.swift:12 — representative stored state or nearest verified lifecycle anchor.
struct ContentView: View {
@State var telescope: Entity? = nil
// ...
}| Owner | Object or state | Relationship | Mutation authority |
|---|---|---|---|
ContentView |
Entity as telescope |
owns a SwiftUI-managed reference slot | The owning type coordinates writes |
ContentView |
RotationAxis as axis |
owns SwiftUI value state | The owning type coordinates writes |
RotationSystem |
EntityQuery as rotationQuery |
creates and retains | The owning type coordinates writes |
ContentView |
Bool as isRotating |
owns SwiftUI value state | The owning type coordinates writes |
Ownership is intentionally narrow: environment, bindings, observed objects, weak links, and delegate callbacks do not prove lifetime ownership. Initialized stored services and wrapper-managed state do; entities added inside a RealityKit content closure belong to that entity graph.
Class and protocol design
| Type | Responsibility | Depends on or conforms to |
|---|---|---|
RotationApp (Rotation/RotationApp.swift:12) |
Declares app lifecycle and top-level dependency lifetime. | App |
ContentView (Rotation/ContentView.swift:11) |
Presents UI and forwards gestures or lifecycle events. | View |
RotationSystem (Packages/SceneAssets/Sources/SceneAssets/RotationSystem.swift:11) |
Updates entities matching a RealityKit component query. | System |
RotationComponent (Packages/SceneAssets/Sources/SceneAssets/RotationComponent.swift:9) |
Stores RealityKit entity data. | Component, Codable |
The reviewed source defines no local substitution protocol. Its App, View, delegate, renderer, ARKit, and RealityKit conformances are framework-facing contracts, so this document does not label the whole app protocol-oriented.
Access control
| Symbol | Access | Verified effect | Likely rationale |
|---|---|---|---|
public var id: String { (Packages/SceneAssets/Sources/SceneAssets/RotationAxis.swift:8) |
public |
The symbol is available to importing modules, subject to its containing type’s visibility. | Inference: Expose an intentional package or cross-target surface. |
No reviewed Swift access example uses fileprivate, private(set), open; declarations without a modifier are internal.
Reference code
Packages/SceneAssets/Sources/SceneAssets/RotationAxis.swift:8 — representative visibility boundary.
public var id: String {
return self.rawValue
}Logic ownership and placement
| Logic | Owning type or file | Placement rationale |
|---|---|---|
| Application/command lifecycle | RotationApp |
The executable boundary determines app, controller, scene, or command lifetime. |
| Presentation and user intent | ContentView |
The view/controller forwards input and owns only presentation-local work. |
| Framework/session/render coordination | RotationSystem |
The role-named collaborator isolates long-lived or per-frame work from presentation code. |
| Per-entity data and repeated behavior | Packages/SceneAssets/Sources/SceneAssets/RotationSystem.swift:11 |
Components carry data; the system queries and updates matching entities. |
| Authored scene composition | Packages/SceneAssets/Package.realitycomposerpro/ProjectData/main.json |
Reality Composer Pro owns hierarchy, materials, animation, or behavior that Swift loads and coordinates. |
Design patterns
| Pattern | Source evidence | Purpose or tradeoff |
|---|---|---|
| SwiftUI scene composition | Rotation/RotationApp.swift:12 |
Keeps windows, volumes, and immersive presentation visible at the app boundary. |
| UI–RealityKit bridge | Rotation/ContentView.swift:18 |
Builds or hosts the RealityKit entity graph from SwiftUI or a platform view/controller lifecycle. |
| Entity-component-system | Packages/SceneAssets/Sources/SceneAssets/RotationSystem.swift:11 |
Stores per-entity data in components and advances repeated behavior in registered systems. |
| Component-system update loop | Packages/SceneAssets/Sources/SceneAssets/RotationSystem.swift:11 |
Stores rotation speed on each entity and advances matching entities through a registered RealityKit system. |
Naming conventions
- Role suffixes are evidence, not decoration: App:
RotationApp; System:RotationSystem; Component:RotationComponent; View:ContentView. - ECS names pair data and behavior: components
RotationComponent; systemsRotationSystem. - Protocols: no app-defined protocol in the reviewed source.
- Commands use verb-led methods:
update. - Files and folders use primary-type or responsibility names such as
Views,Models,Rendering,Components,Systems,Packages, or feature names where those boundaries exist.
Architecture takeaways
- Treat
RotationAppas the owner of executable or scene lifecycle, not automatically as the owner of every entity created later. - Keep view/controller input near presentation, but move sessions, reconstruction, capture, rendering, shared game state, or documents into stable owners when their lifetime exceeds one callback or render pass.
- Use components for per-entity data and systems for repeated simulation instead of centralizing every update in a view model or controller.
- Count authored Reality Composer Pro assets as implementation; the Swift shell is not the complete architecture.
- The compact source does not justify repository, coordinator, or protocol layers beyond boundaries the sample actually declares.
Source map
| Source file | Relevant symbols |
|---|---|
Packages/SceneAssets/Sources/SceneAssets/RotationSystem.swift:11 |
RotationSystem |
Packages/SceneAssets/Sources/SceneAssets/RotationComponent.swift:9 |
RotationComponent |
Rotation/RotationApp.swift:12 |
RotationApp |
Rotation/ContentView.swift:11 |
ContentView |
Packages/SceneAssets/Sources/SceneAssets/RotationAxis.swift:7 |
RotationAxis |
Packages/SceneAssets/Sources/SceneAssets/SceneAssets.swift:1 |
Feature implementation |