Sample CodevisionOSReviewed 2026-07-21View on Apple Developer

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

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

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; systems RotationSystem.
  • 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 RotationApp as 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