Configuring Collision in RealityKit
At a glance
| Item | Summary |
|---|---|
| Purpose | Use collision groups and collision filters to control which objects collide. |
| App architecture | AppDelegate installs ViewController, which owns the ARView, creates custom entities, and assigns collision groups, masks, and event subscriptions that decide which pairs interact. |
| Main patterns | UIKit lifecycle composition, UI–RealityKit bridge, Delegate callback adapter, Collision filter matrix |
| Project style | Code-rich sample with 4 scanned Swift file(s) and 428 implementation line(s). |
Project structure
Source bundle/
└── RealityKitCollisionGroups/
├── ViewController.swift # ViewController
├── Custom Entities/
│ ├── Entities.swift # MovableEntity, BoxEntity, BeveledBoxEntity
│ └── PlaneEntity.swift # PlaneEntity
└── AppDelegate.swift # AppDelegate
Structure observations
- The runtime boundary is UIApplicationDelegate + UIViewController; 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
flowchart LR
AppDelegate_1["AppDelegate"]
UIApplicationDelegate___UIViewController_2["UIApplicationDelegate + UIViewController"]
ViewController_3["ViewController"]
RealityKit_entity_graph_4["RealityKit entity graph"]
RealityKit_collision_filters_events_5["RealityKit collision filters/events"]
AppDelegate_1 --> UIApplicationDelegate___UIViewController_2
UIApplicationDelegate___UIViewController_2 --> ViewController_3
ViewController_3 --> RealityKit_entity_graph_4
RealityKit_entity_graph_4 --> RealityKit_collision_filters_events_5
Reference code
RealityKitCollisionGroups/AppDelegate.swift:11 — executable or app-lifecycle anchor.
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
}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
ViewController *-- BoxEntity : cube1
ViewController *-- BoxEntity : cube2
ViewController *-- BoxEntity : cube3
ViewController *-- SphereEntity : sphere1
Ownership evidence
RealityKitCollisionGroups/ViewController.swift:44 — representative stored state or nearest verified lifecycle anchor.
let cube1 = BoxEntity(size: 0.05, color: .green, roughness: 0.0)
let cube2 = BoxEntity(size: 0.05, color: .green, roughness: 0.0)
let cube3 = BoxEntity(size: 0.05, color: .green, roughness: 0.0)
let sphere1 = SphereEntity(size: 0.05, color: .orange, roughness: 1.0)
let sphere2 = SphereEntity(size: 0.05, color: .orange, roughness: 1.0)
let sphere3 = SphereEntity(size: 0.05, color: .orange, roughness: 1.0)| Owner | Object or state | Relationship | Mutation authority |
|---|---|---|---|
ViewController |
BoxEntity as cube1 |
creates and retains | The owning type coordinates writes |
ViewController |
BoxEntity as cube2 |
creates and retains | The owning type coordinates writes |
ViewController |
BoxEntity as cube3 |
creates and retains | The owning type coordinates writes |
ViewController |
SphereEntity as sphere1 |
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 |
|---|---|---|
AppDelegate (RealityKitCollisionGroups/AppDelegate.swift:11) |
Declares app lifecycle and top-level dependency lifetime. | UIResponder, UIApplicationDelegate |
ViewController (RealityKitCollisionGroups/ViewController.swift:13) |
Coordinates long-lived framework or cross-view work. | UIViewController, UIGestureRecognizerDelegate |
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 |
|---|---|---|---|
fileprivate func configureEntityAccessibility() { (RealityKitCollisionGroups/ViewController.swift:166) |
fileprivate |
Use is limited to declarations in this source file. | Inference: Share with same-file helpers without making the symbol module-wide. |
No reviewed Swift access example uses private(set), public, open; declarations without a modifier are internal.
Reference code
RealityKitCollisionGroups/ViewController.swift:166 — representative visibility boundary.
fileprivate func configureEntityAccessibility() {
// ...
}Logic ownership and placement
| Logic | Owning type or file | Placement rationale |
|---|---|---|
| Application/command lifecycle | AppDelegate |
The executable boundary determines app, controller, scene, or command lifetime. |
| Presentation and user intent | ViewController |
The view/controller forwards input and owns only presentation-local work. |
Design patterns
| Pattern | Source evidence | Purpose or tradeoff |
|---|---|---|
| UIKit lifecycle composition | RealityKitCollisionGroups/AppDelegate.swift:11 |
Uses the application delegate and view controller as the explicit lifecycle and scene-ownership boundary. |
| UI–RealityKit bridge | RealityKitCollisionGroups/ViewController.swift:13 |
Builds or hosts the RealityKit entity graph from SwiftUI or a platform view/controller lifecycle. |
| Delegate callback adapter | RealityKitCollisionGroups/AppDelegate.swift:11 |
Inverts imperative framework callbacks into the sample’s owning controller, coordinator, or model. |
| Collision filter matrix | RealityKitCollisionGroups/ViewController.swift:80 |
Expresses interaction policy as group and mask values rather than conditional checks in every collision callback. |
Naming conventions
- Role suffixes are evidence, not decoration: Controller:
ViewController. - Protocols: no app-defined protocol in the reviewed source.
- Commands use verb-led methods:
tappedResetButton,toggleDebugDrawing,viewDidLoad,setInitialTransforms,setPhysicsModeAll,setCollisionFilters,configureEntityAccessibility,setScene. - 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
AppDelegateas 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.
Source map
| Source file | Relevant symbols |
|---|---|
RealityKitCollisionGroups/ViewController.swift:13 |
ViewController |
RealityKitCollisionGroups/Custom Entities/Entities.swift:13 |
MovableEntity, BoxEntity, BeveledBoxEntity, SphereEntity |
RealityKitCollisionGroups/Custom Entities/PlaneEntity.swift:13 |
PlaneEntity |
RealityKitCollisionGroups/AppDelegate.swift:11 |
AppDelegate |