mcpField
A
axiom-realitykit-diag

axiom-realitykit-diag

github.com/charleswiltgen开发1.2k133 次安装今天更新
代码仓库

关于 axiom-realitykit-diag

面向开发者的 RealityKit 诊断技能,按症状排查场景、AR、交互、渲染、物理和同步问题,并提供调试可视化与代码检查方法。

主要功能

  1. 01按症状整理 RealityKit 检查
  2. 02调试可视化指引
  3. 03可见性与跟踪诊断
  4. 04手势与碰撞检查
  5. 05性能和材质检查
  6. 06物理与同步排查

适用场景

  1. 01排查实体未显示在场景中
  2. 02追查 3D 手势无响应
  3. 03检查帧率下降或材质异常
  4. 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

常见错误

错误耗时修复方法
交互实体上没有 CollisionComponent15-30 分钟entity.generateCollisionShapes(recursive: true)
visionOS 上缺少 InputTargetComponent10-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