Transforming RealityKit entities using gestures
At a glance
| Item | Summary |
|---|---|
| Purpose | Build a RealityKit component to support standard visionOS gestures on any entity. |
| App architecture | EntityGestureApp loads content in ContentView; GestureComponent stores per-entity interaction configuration and gesture modifiers translate drag, rotate, and scale input into entity transforms. |
| Main patterns | SwiftUI scene composition, UI–RealityKit bridge, Authored-content boundary, Entity gesture component |
| Project style | Code-rich sample with 8 scanned Swift file(s) and 523 implementation line(s). |
Project structure
Source bundle/
├── Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift # EntityGestureState, GestureComponent
├── EntityGestures/ContentView.swift # ContentView
├── EntityGestures/EntityGestureApp.swift # EntityGestureApp
├── Packages/RealityKitContent/Sources/RealityKitContent/Extensions/EntityExtensions.swift
├── Packages/RealityKitContent/Sources/RealityKitContent/Extensions/GestureExtensions.swift
├── Packages/RealityKitContent/Sources/RealityKitContent/Extensions/RealityViewExtensions.swift
├── Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.swift
└── Packages/RealityKitContent/Package.realitycomposerpro/ProjectData/main.json # authored RealityKit content
Structure observations
- The runtime boundary is WindowGroup + volumetric window; the tree is pruned to lifecycle, state, framework, rendering, and ECS files.
- The source is Swift; role-named types and feature folders separate the major responsibilities.
- 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
EntityGestureApp_1["EntityGestureApp"]
WindowGroup___volumetric_window_2["WindowGroup + volumetric window"]
ContentView_3["ContentView"]
GestureComponent_4["GestureComponent"]
RealityKit_entity_graph_5["RealityKit entity graph"]
targeted_gestures___entity_state_6["targeted gestures + entity state"]
EntityGestureApp_1 --> WindowGroup___volumetric_window_2
WindowGroup___volumetric_window_2 --> ContentView_3
ContentView_3 --> GestureComponent_4
GestureComponent_4 --> RealityKit_entity_graph_5
RealityKit_entity_graph_5 --> targeted_gestures___entity_state_6
Reference code
EntityGestures/EntityGestureApp.swift:12 — executable or app-lifecycle anchor.
struct EntityGestureApp: 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
GestureComponent *-- Entity : pivotEntity
EntityGestureState --> Entity : targetedEntity
EntityGestureState --> Entity : pivotEntity
GestureComponent *-- Transform : targetPivotTransform
Ownership evidence
Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:120 — representative stored state or nearest verified lifecycle anchor.
@MainActor
public struct GestureComponent: Component, Codable {
// ...
let pivotEntity = Entity()
// ...
}| Owner | Object or state | Relationship | Mutation authority |
|---|---|---|---|
GestureComponent |
Entity as pivotEntity |
creates and retains | The owning type coordinates writes |
EntityGestureState |
Entity as targetedEntity |
stores and coordinates | The owning type coordinates writes |
EntityGestureState |
Entity as pivotEntity |
stores and coordinates | The owning type coordinates writes |
GestureComponent |
Transform as targetPivotTransform |
creates and retains | 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 |
|---|---|---|
EntityGestureApp (EntityGestures/EntityGestureApp.swift:12) |
Declares app lifecycle and top-level dependency lifetime. | App |
ContentView (EntityGestures/ContentView.swift:12) |
Presents UI and forwards gestures or lifecycle events. | View |
GestureComponent (Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:55) |
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 canDrag: Bool = true (Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:58) |
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/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:58 — representative visibility boundary.
@MainActor
public struct GestureComponent: Component, Codable {
// ...
public var canDrag: Bool = true
// ...
}Logic ownership and placement
| Logic | Owning type or file | Placement rationale |
|---|---|---|
| Application/command lifecycle | EntityGestureApp |
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 | GestureComponent |
The role-named collaborator isolates long-lived or per-frame work from presentation code. |
| Authored scene composition | Packages/RealityKitContent/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 | EntityGestures/EntityGestureApp.swift:12 |
Keeps windows, volumes, and immersive presentation visible at the app boundary. |
| UI–RealityKit bridge | EntityGestures/ContentView.swift:50 |
Builds or hosts the RealityKit entity graph from SwiftUI or a platform view/controller lifecycle. |
| Authored-content boundary | EntityGestures/ContentView.swift:10 |
Treats Reality Composer Pro assets as implementation and keeps Swift responsible for loading and runtime coordination. |
| Entity gesture component | Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:11 |
Stores interaction policy with the entity and keeps drag, rotation, and scale translation in reusable gesture modifiers. |
Naming conventions
- Role suffixes are evidence, not decoration: App:
EntityGestureApp; Component:GestureComponent; View:ContentView. - ECS names pair data and behavior: components
GestureComponent; systems none. - Protocols: no app-defined protocol in the reviewed source.
- Commands use verb-led methods:
onChanged,handlePivotDrag,handleFixedDrag,onEnded,useGestureComponent,installGestures. - 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
EntityGestureAppas 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.
- Count authored Reality Composer Pro assets as implementation; the Swift shell is not the complete architecture.
Source map
| Source file | Relevant symbols |
|---|---|
Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:11 |
EntityGestureState, GestureComponent |
EntityGestures/ContentView.swift:12 |
ContentView |
EntityGestures/EntityGestureApp.swift:12 |
EntityGestureApp |
Packages/RealityKitContent/Sources/RealityKitContent/Extensions/EntityExtensions.swift:1 |
Feature implementation |
Packages/RealityKitContent/Sources/RealityKitContent/Extensions/GestureExtensions.swift:1 |
Feature implementation |
Packages/RealityKitContent/Sources/RealityKitContent/Extensions/RealityViewExtensions.swift:1 |
Feature implementation |
Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.swift:1 |
Feature implementation |