Sample CodevisionOSReviewed 2026-07-21View on Apple Developer

Simulating physics with collisions in your visionOS app

At a glance

Item Summary
Purpose Create entities that behave and react like physical objects in a RealityKit view.
App architecture PhysicsBodiesApp presents MainView; gesture state lives in components and SphereAttractionSystem applies repeated physics behavior to matching entities while RealityKit resolves collisions.
Main patterns SwiftUI scene composition, UI–RealityKit bridge, Entity-component-system, Physics component-system loop
Project style Code-rich sample with 10 scanned Swift file(s) and 440 implementation line(s).

Project structure

Source bundle/
└── PhysicsBodies/
    ├── MainView.swift  # MainView
    ├── SphereAttractionSystem.swift  # SphereAttractionSystem
    ├── PhysicsBodiesApp.swift  # PhysicsBodiesApp
    ├── SphereAttractionComponent.swift  # SphereAttractionComponent
    ├── EntityDragGesture.swift  # EntityDragGesture, GestureStateComponent
    ├── ContainmentCollisionBox.swift  # ContainmentCollisionBox
    └── ForceDragGesture.swift  # ForceDragGesture

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.

Overall architecture

Reference code

PhysicsBodies/PhysicsBodiesApp.swift:11 — executable or app-lifecycle anchor.

struct PhysicsBodiesApp: App {
    var body: some Scene {
        WindowGroup {
            MainView()
        }.windowStyle(.volumetric)
    }
}

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

PhysicsBodies/MainView.swift:13 — representative stored state or nearest verified lifecycle anchor.

struct MainView: View {
    // ...
    @State var containmentCollisionBox = ContainmentCollisionBox()
    // ...
}
Owner Object or state Relationship Mutation authority
MainView ContainmentCollisionBox as containmentCollisionBox creates and retains The owning type coordinates writes
SphereAttractionSystem EntityQuery as entityQuery stores and coordinates The owning type coordinates writes
GestureStateComponent Closure as closure stores and coordinates The owning type coordinates writes
ContainmentCollisionBox BoundingBox as lastBoundingBox stores and coordinates 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
PhysicsBodiesApp (PhysicsBodies/PhysicsBodiesApp.swift:11) Declares app lifecycle and top-level dependency lifetime. App
MainView (PhysicsBodies/MainView.swift:11) Presents UI and forwards gestures or lifecycle events. View
SphereAttractionSystem (PhysicsBodies/SphereAttractionSystem.swift:11) Updates entities matching a RealityKit component query. System
GestureStateComponent (PhysicsBodies/EntityDragGesture.swift:12) Stores RealityKit entity data. Component
SphereAttractionComponent (PhysicsBodies/SphereAttractionComponent.swift:11) Stores RealityKit entity data. Component

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
private let defaultMass1Kg = Float(1.0) (PhysicsBodies/Entity+CollisionPhysicsBox.swift:12) private Use stays inside the declaration and same-file extensions permitted by Swift. Inference: Hide lifecycle-sensitive state or an implementation step.

No reviewed Swift access example uses fileprivate, private(set), public, open; declarations without a modifier are internal.

Reference code

PhysicsBodies/Entity+CollisionPhysicsBox.swift:12 — representative visibility boundary.

private let defaultMass1Kg = Float(1.0)

Logic ownership and placement

Logic Owning type or file Placement rationale
Application/command lifecycle PhysicsBodiesApp The executable boundary determines app, controller, scene, or command lifetime.
Presentation and user intent MainView The view/controller forwards input and owns only presentation-local work.
Framework/session/render coordination SphereAttractionSystem The role-named collaborator isolates long-lived or per-frame work from presentation code.
Per-entity data and repeated behavior PhysicsBodies/SphereAttractionSystem.swift:11 Components carry data; the system queries and updates matching entities.

Design patterns

Pattern Source evidence Purpose or tradeoff
SwiftUI scene composition PhysicsBodies/PhysicsBodiesApp.swift:11 Keeps windows, volumes, and immersive presentation visible at the app boundary.
UI–RealityKit bridge PhysicsBodies/MainView.swift:17 Builds or hosts the RealityKit entity graph from SwiftUI or a platform view/controller lifecycle.
Entity-component-system PhysicsBodies/SphereAttractionSystem.swift:11 Stores per-entity data in components and advances repeated behavior in registered systems.
Physics component-system loop PhysicsBodies/SphereAttractionSystem.swift:11 Stores participation on entities and applies repeated forces through a registered system while RealityKit resolves contacts.

Naming conventions

  • Role suffixes are evidence, not decoration: App: PhysicsBodiesApp; System: SphereAttractionSystem; Component: GestureStateComponent, SphereAttractionComponent; View: MainView.
  • ECS names pair data and behavior: components GestureStateComponent, SphereAttractionComponent; systems SphereAttractionSystem.
  • Protocols: no app-defined protocol in the reviewed source.
  • Commands use verb-led methods: addSpheres, update, startPosition.
  • 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 PhysicsBodiesApp 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.

Source map

Source file Relevant symbols
PhysicsBodies/MainView.swift:11 MainView
PhysicsBodies/SphereAttractionSystem.swift:11 SphereAttractionSystem
PhysicsBodies/PhysicsBodiesApp.swift:11 PhysicsBodiesApp
PhysicsBodies/SphereAttractionComponent.swift:11 SphereAttractionComponent
PhysicsBodies/EntityDragGesture.swift:11 EntityDragGesture, GestureStateComponent
PhysicsBodies/ContainmentCollisionBox.swift:12 ContainmentCollisionBox
PhysicsBodies/ForceDragGesture.swift:12 ForceDragGesture