关于 axiom-realitykit-diag
面向开发者的 RealityKit 诊断技能,按症状排查场景、AR、交互、渲染、物理和同步问题,并提供调试可视化与代码检查方法。
主要功能
- 01按症状整理 RealityKit 检查
- 02调试可视化指引
- 03可见性与跟踪诊断
- 04手势与碰撞检查
- 05性能和材质检查
- 06物理与同步排查
适用场景
- 01排查实体未显示在场景中
- 02追查 3D 手势无响应
- 03检查帧率下降或材质异常
- 04诊断物理或多人同步问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ charleswiltgen/ axiom --skill axiom-realitykit-diag安装后在 Claude Code 中输入/axiom-realitykit-diag确认已加载。
详细介绍
RealityKit 诊断
针对常见 RealityKit 问题的系统化诊断,并标注耗时。
何时使用此诊断技能
出现以下情况时使用此技能:
- 添加了实体,但在场景中不可见
- AR 锚点未能跟踪,或内容漂浮
- 点击/拖动手势对 3D 实体没有响应
- 帧率下降或画面卡顿
- 材质显示异常(太暗、太亮或颜色不正确)
- 多人游戏中的实体未能在设备间同步
- 物理体没有发生碰撞,或彼此穿透
有关 RealityKit 架构模式和最佳实践,请参阅 axiom-realitykit。有关 API 参考,请参阅 axiom-realitykit-ref。
必须先执行的步骤:启用调试可视化
耗时:10 秒,而不是数小时盲目调试
// 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
如果使用 .showPhysics 看不到碰撞形状,说明你的 CollisionComponent 缺失或配置有误。请先修复碰撞,再调试手势或物理效果。
症状 1:实体不可见
节省时间:30-60 分钟 → 2-5 分钟
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
快速诊断
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)")
}
症状 2:锚点未能跟踪
节省时间:20-45 分钟 → 3-5 分钟
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
症状 3:手势没有响应
节省时间:15-30 分钟 → 2-3 分钟
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
快速诊断
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)")
}
}
症状 4:性能问题
节省时间:1-3 小时 → 10-20 分钟
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.
症状 5:材质显示异常
节省时间:15-45 分钟 → 5-10 分钟
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: ...)
症状 6:物理效果无效
节省时间:20-40 分钟 → 5-10 分钟
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
症状 7:多人同步问题
节省时间:30-60 分钟 → 10-15 分钟
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
常见错误
| 错误 | 耗时 | 修复方法 |
|---|---|---|
| 交互实体上没有 CollisionComponent | 15-30 分钟 | entity.generateCollisionShapes(recursive: true) |
| visionOS 上缺少 InputTargetComponent | 10-20 分钟 | 添加 InputTargetComponent() |
| 手势附加在错误的视图上(不是 RealityView) | 10-15 分钟 | 将 .gesture() 附加到 RealityView |
| USD 模型的实体缩放比例错误 | 15-30 分钟 | 检查单位:米还是厘米 |
| 非 AR 场景中没有光照 | 10-20 分钟 | 添加 DirectionalLightComponent |
| 在 System 中存储实体引用 | 30-60 分钟的崩溃调试时间 | 每帧使用 EntityQuery 进行查询 |
| 组件未注册 | 10-15 分钟 | 在应用初始化时调用 registerComponent() |
| 系统未注册 | 10-15 分钟 | 在场景加载前调用 registerSystem() |
| 物理效果涉及不同锚点 | 20-40 分钟 | 将交互实体置于同一锚点下 |
| 每帧都调用 generateCollisionShapes | 性能下降 | 在设置期间调用一次 |
诊断速查表
| 症状 | 首要检查项 | 节省时间 |
|---|---|---|
| 不可见 | 是否有 ModelComponent?缩放是否大于 0? | 30-60 分钟 |
| 手势没有响应 | 是否有 CollisionComponent? | 15-30 分钟 |
| 未能跟踪 | 锚点类型是否与环境匹配? | 20-45 分钟 |
| 帧率下降 | 实体数量?资源是否共享? | 1-3 小时 |
| 颜色错误 | 是否有光照?Metallic 值是多少? | 15-45 分钟 |
| 没有碰撞 | 双方是否都有 CollisionComponent?是否位于同一锚点? | 20-40 分钟 |
| 没有同步 | 是否有 SynchronizationComponent?是否遵循 Codable? | 30-60 分钟 |
| 模拟器运行正常,设备崩溃 | Metal 功能?纹理格式? | 15-30 分钟 |
症状 8:模拟器运行正常,设备崩溃
耗时:15-30 分钟(通常会被误诊为模型问题)
Q1: Is the crash a Metal error (MTLCommandBuffer, shader compilation)?
├─ YES → Simulator uses software rendering, device uses real GPU
│ Common causes:
│ - Custom Metal shaders with unsupported features
│ - Texture formats not supported on device GPU
│ - Exceeding device texture size limits (max 8192x8192 on older)
│ Fix: Check device GPU family, use supported formats
│
└─ NO → Check next
Q2: Is it an out-of-memory crash?
├─ YES → Simulator has more RAM available
│ Common: Large USDZ files with uncompressed textures
│ Fix: Compress textures, reduce polygon count, use LOD
│ Check: USDZ file size (keep < 50MB for reliable loading)
│
└─ NO → Check next
Q3: Is it an AR-related crash (camera, tracking)?
├─ YES → Simulator has no real camera/sensors
│ Fix: Test AR features on device only, use simulator for UI/layout
│
└─ NO → Check device capabilities
- A12+ required for RealityKit
- LiDAR for scene reconstruction
- TrueDepth for face tracking
资源
WWDC:2019-603、2019-605、2023-10080、2024-10103
文档:/realitykit、/realitykit/entity、/realitykit/collisioncomponent、/realitykit/physicsbodycomponent
技能:axiom-realitykit、axiom-realitykit-ref
评论
支持 Markdown