axiom-realitykit-diag
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-realitykit-diag
Agent 安装分布
Skill 文档
RealityKit Diagnostics
Systematic diagnosis for common RealityKit issues with time-cost annotations.
When to Use This Diagnostic Skill
Use this skill when:
- Entity added but not visible in the scene
- AR anchor not tracking or content floating
- Tap/drag gestures not responding on 3D entities
- Frame rate dropping or stuttering
- Material looks wrong (too dark, too bright, incorrect colors)
- Multiplayer entities not syncing across devices
- Physics bodies not colliding or passing through each other
For RealityKit architecture patterns and best practices, see axiom-realitykit. For API reference, see axiom-realitykit-ref.
Mandatory First Step: Enable Debug Visualization
Time cost: 10 seconds vs hours of blind debugging
// In your RealityView or ARView setup
#if DEBUG
// Xcode: Debug â Attach to Process â Show RealityKit Statistics
// Or enable in code:
arView.debugOptions = [
.showStatistics, // Entity count, draw calls, FPS
.showPhysics, // Collision shapes
.showAnchorOrigins, // Anchor positions
.showAnchorGeometry // Detected plane geometry
]
#endif
If you can’t see collision shapes with .showPhysics, your CollisionComponent is missing or misconfigured. Fix collision before debugging gestures or physics.
Symptom 1: Entity Not Visible
Time saved: 30-60 min â 2-5 min
Entity added but nothing appears
â
ââ Is the entity added to the scene?
â ââ NO â Add to RealityView content:
â content.add(entity)
â â Entities must be in the scene graph to render
â
ââ Does the entity have a ModelComponent?
â ââ NO â Add mesh and material:
â entity.components[ModelComponent.self] = ModelComponent(
â mesh: .generateBox(size: 0.1),
â materials: [SimpleMaterial(color: .red, isMetallic: false)]
â )
â â Bare Entity is invisible â it's just a container
â
ââ Is the entity's scale zero or nearly zero?
â ââ CHECK â Print: entity.scale
â USD models may import with unexpected scale.
â Try: entity.scale = SIMD3(repeating: 0.01) for meter-scale models
â
ââ Is the entity behind the camera?
â ââ CHECK â Print: entity.position(relativeTo: nil)
â In RealityKit, -Z is forward (toward screen).
â Try: entity.position = SIMD3(0, 0, -0.5) (half meter in front)
â
ââ Is the entity inside another object?
â ââ CHECK â Move to a known visible position:
â entity.position = SIMD3(0, 0, -1)
â
ââ Is the entity's isEnabled set to false?
â ââ CHECK â entity.isEnabled = true
â Also check parent: entity.isEnabledInHierarchy
â
ââ Is the entity on an untracked anchor?
â ââ CHECK â Verify anchor is tracking:
â entity.isAnchored (should be true)
â If using plane anchor, ensure surface is detected first
â
ââ Is the material transparent or OcclusionMaterial?
ââ CHECK â Inspect material:
If using PhysicallyBasedMaterial, check baseColor is not black
If using blending = .transparent, check opacity > 0
Quick Diagnostic
func diagnoseVisibility(_ entity: Entity) {
print("Name: \(entity.name)")
print("Is enabled: \(entity.isEnabled)")
print("In hierarchy: \(entity.isEnabledInHierarchy)")
print("Is anchored: \(entity.isAnchored)")
print("Position (world): \(entity.position(relativeTo: nil))")
print("Scale: \(entity.scale)")
print("Has model: \(entity.components[ModelComponent.self] != nil)")
print("Children: \(entity.children.count)")
}
Symptom 2: Anchor Not Tracking
Time saved: 20-45 min â 3-5 min
AR content not appearing or floating
â
ââ Is the AR session running?
â ââ For RealityView on iOS 18+, AR runs automatically
â For ARView, check: arView.session.isRunning
â
ââ Is SpatialTrackingSession configured? (iOS 18+)
â ââ CHECK â Ensure tracking modes requested:
â let config = SpatialTrackingSession.Configuration(
â tracking: [.plane, .object])
â let result = await session.run(config)
â if let notSupported = result {
â // Handle unsupported modes
â }
â
ââ Is the anchor type appropriate for the environment?
â ââ .plane(.horizontal) â Need a flat surface visible to camera
â ââ .plane(.vertical) â Need a wall visible to camera
â ââ .image â Image must be in "AR Resources" asset catalog
â ââ .face â Front camera required (not rear)
â ââ .body â Full body must be visible
â
ââ Is minimumBounds too large?
â ââ CHECK â Reduce minimum bounds:
â AnchorEntity(.plane(.horizontal, classification: .any,
â minimumBounds: SIMD2(0.1, 0.1))) // Smaller = detects sooner
â
ââ Is the device supported?
â ââ CHECK â Plane detection requires A12+ chip
â Face tracking requires TrueDepth camera
â Body tracking requires A12+ chip
â
ââ Is the environment adequate?
ââ CHECK â AR needs:
- Adequate lighting (not too dark)
- Textured surfaces (not blank walls)
- Stable device position during initial detection
Symptom 3: Gesture Not Responding
Time saved: 15-30 min â 2-3 min
Tap/drag on entity does nothing
â
ââ Does the entity have a CollisionComponent?
â ââ NO â Add collision shapes:
â entity.generateCollisionShapes(recursive: true)
â // or manual:
â entity.components[CollisionComponent.self] = CollisionComponent(
â shapes: [.generateBox(size: SIMD3(0.1, 0.1, 0.1))])
â â Collision shapes are REQUIRED for gesture hit testing
â
ââ [visionOS] Does the entity have InputTargetComponent?
â ââ NO â Add it:
â entity.components[InputTargetComponent.self] = InputTargetComponent()
â â Required on visionOS for gesture input
â
ââ Is the gesture attached to the RealityView?
â ââ CHECK â Gesture must be on the view, not the entity:
â RealityView { content in ... }
â .gesture(TapGesture().targetedToAnyEntity().onEnded { ... })
â
ââ Is the collision shape large enough to hit?
â ââ CHECK â Enable .showPhysics to see shapes
â Shapes too small = hard to tap.
â Try: .generateBox(size: SIMD3(repeating: 0.1)) minimum
â
ââ Is the entity behind another entity?
â ââ CHECK â Front entities may block gestures on back entities
â Ensure collision is on the intended target
â
ââ Is the entity enabled?
ââ CHECK â entity.isEnabled must be true
Disabled entities don't receive input
Quick Diagnostic
func diagnoseGesture(_ entity: Entity) {
print("Has collision: \(entity.components[CollisionComponent.self] != nil)")
print("Has input target: \(entity.components[InputTargetComponent.self] != nil)")
print("Is enabled: \(entity.isEnabled)")
print("Is anchored: \(entity.isAnchored)")
if let collision = entity.components[CollisionComponent.self] {
print("Collision shapes: \(collision.shapes.count)")
}
}
Symptom 4: Performance Problems
Time saved: 1-3 hours â 10-20 min
Frame rate dropping or stuttering
â
ââ How many entities are in the scene?
â ââ CHECK â Print entity count:
â var count = 0
â func countEntities(_ entity: Entity) {
â count += 1
â for child in entity.children { countEntities(child) }
â }
â Under 100: unlikely to be entity count
â 100-500: review for optimization
â 500+: definitely needs optimization
â
ââ Are mesh/material resources shared?
â ââ NO â Share resources across identical entities:
â let sharedMesh = MeshResource.generateBox(size: 0.05)
â let sharedMaterial = SimpleMaterial(color: .white, isMetallic: false)
â // Reuse for all instances
â â RealityKit batches entities with identical resources
â
ââ Is a System creating components every frame?
â ââ CHECK â Look for allocations in update():
â Creating ModelComponent, CollisionComponent, or materials
â every frame causes GC pressure.
â Cache resources, only update when values change.
â
ââ Are collision shapes mesh-based?
â ââ CHECK â Replace generateCollisionShapes(recursive: true)
â with simple shapes (box, sphere, capsule) for dynamic entities
â
ââ Is generateCollisionShapes called repeatedly?
â ââ CHECK â Call once during setup, not every frame
â
ââ Are there too many physics bodies?
â ââ CHECK â Dynamic bodies are most expensive.
â Convert distant/static objects to .static mode.
â Remove physics from non-interactive entities.
â
ââ Is the model polygon count too high?
ââ CHECK â Decimate models for real-time use.
Target: <100K triangles total for mobile AR.
Use LOD (Level of Detail) for distant objects.
Symptom 5: Material Looks Wrong
Time saved: 15-45 min â 5-10 min
Colors, lighting, or textures look incorrect
â
ââ Is the scene too dark?
â ââ CHECK â Missing environment lighting:
â Add DirectionalLightComponent or EnvironmentResource
â In AR, RealityKit uses real-world lighting automatically
â In non-AR, you must provide lighting explicitly
â
ââ Is the baseColor set?
â ââ CHECK â PhysicallyBasedMaterial defaults to white
â material.baseColor = .init(tint: .red)
â If using a texture, verify it loaded:
â try TextureResource(named: "albedo")
â
ââ Is metallic set incorrectly?
â ââ CHECK â metallic = 1.0 makes surfaces mirror-like
â Most real objects: metallic = 0.0
â Only metals (gold, silver, chrome): metallic = 1.0
â
ââ Is the texture semantic wrong?
â ââ CHECK â Use correct semantic:
â .color for albedo/baseColor textures
â .raw for data textures (metallic, roughness)
â .normal for normal maps
â .hdrColor for HDR textures
â
ââ Is the model upside down or inside out?
â ââ CHECK â Try:
â material.faceCulling = .none (shows both sides)
â If that fixes it, the model normals are flipped
â
ââ Is blending/transparency unexpected?
ââ CHECK â material.blending
Default is .opaque
For transparency: .transparent(opacity: ...)
Symptom 6: Physics Not Working
Time saved: 20-40 min â 5-10 min
Objects pass through each other or don't collide
â
ââ Do both entities have CollisionComponent?
â ââ NO â Both sides of a collision need CollisionComponent
â
ââ Does the moving entity have PhysicsBodyComponent?
â ââ NO â Add physics body:
â entity.components[PhysicsBodyComponent.self] = PhysicsBodyComponent(
â mode: .dynamic)
â
ââ Are collision groups/filters configured correctly?
â ââ CHECK â Entities must be in compatible groups:
â Default: group = .default, mask = .all
â If using custom groups, verify mask includes the other group
â
ââ Is the physics mode correct?
â ââ Two .static bodies â Never collide (both immovable)
â ââ .dynamic + .static â Correct (common setup)
â ââ .dynamic + .dynamic â Both move on collision
â ââ .kinematic + .dynamic â Kinematic pushes dynamic
â
ââ Is the collision shape appropriate?
â ââ CHECK â .showPhysics debug option
â Shape may be too small, offset, or wrong type
â
ââ Are entities on different anchors?
ââ CHECK â "Physics bodies and colliders affect only
entities that share the same anchor" (Apple docs)
Move entities under the same anchor for physics interaction
Symptom 7: Multiplayer Sync Issues
Time saved: 30-60 min â 10-15 min
Entities not appearing on other devices
â
ââ Does the entity have SynchronizationComponent?
â ââ NO â Add it:
â entity.components[SynchronizationComponent.self] =
â SynchronizationComponent()
â
ââ Is the MultipeerConnectivityService set up?
â ââ CHECK â Verify MCSession is connected before syncing
â
ââ Are custom components Codable?
â ââ NO â Non-Codable components don't sync
â struct MyComponent: Component, Codable { ... }
â
ââ Does the entity have an owner?
â ââ CHECK â Only the owner can modify synced properties
â Request ownership before modifying:
â entity.requestOwnership { result in ... }
â
ââ Is the entity anchored?
ââ CHECK â Unanchored entities may not sync position correctly
Use a shared world anchor for reliable positioning
Common Mistakes
| Mistake | Time Cost | Fix |
|---|---|---|
| No CollisionComponent on interactive entity | 15-30 min | entity.generateCollisionShapes(recursive: true) |
| Missing InputTargetComponent on visionOS | 10-20 min | Add InputTargetComponent() |
| Gesture on wrong view (not RealityView) | 10-15 min | Attach .gesture() to RealityView |
| Entity scale wrong for USD model | 15-30 min | Check units: meters vs centimeters |
| No lighting in non-AR scene | 10-20 min | Add DirectionalLightComponent |
| Storing entity refs in System | 30-60 min crash debugging | Query with EntityQuery each frame |
| Components not registered | 10-15 min | Call registerComponent() in app init |
| Systems not registered | 10-15 min | Call registerSystem() before scene load |
| Physics across different anchors | 20-40 min | Put interacting entities under same anchor |
| Calling generateCollisionShapes every frame | Performance degradation | Call once during setup |
Diagnostic Quick Reference
| Symptom | First Check | Time Saved |
|---|---|---|
| Not visible | Has ModelComponent? Scale > 0? | 30-60 min |
| No gesture response | Has CollisionComponent? | 15-30 min |
| Not tracking | Anchor type matches environment? | 20-45 min |
| Frame drops | Entity count? Resource sharing? | 1-3 hours |
| Wrong colors | Has lighting? Metallic value? | 15-45 min |
| No collision | Both have CollisionComponent? Same anchor? | 20-40 min |
| No sync | SynchronizationComponent? Codable? | 30-60 min |
Resources
WWDC: 2019-603, 2019-605, 2023-10080, 2024-10103
Docs: /realitykit, /realitykit/entity, /realitykit/collisioncomponent, /realitykit/physicsbodycomponent
Skills: axiom-realitykit, axiom-realitykit-ref