axiom-realitykit-diag by charleswiltgen/axiom
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-realitykit-diag针对常见 RealityKit 问题提供系统化诊断,并附有耗时标注。
在以下情况时使用此技能:
有关 RealityKit 架构模式和最佳实践,请参阅 axiom-realitykit。有关 API 参考,请参阅 axiom-realitykit-ref。
耗时 : 10 秒 vs 数小时的盲目调试
// 在你的 RealityView 或 ARView 设置中
#if DEBUG
// Xcode: Debug → Attach to Process → Show RealityKit Statistics
// 或者在代码中启用:
arView.debugOptions = [
.showStatistics, // 实体数量、绘制调用、FPS
.showPhysics, // 碰撞形状
.showAnchorOrigins, // 锚点位置
.showAnchorGeometry // 检测到的平面几何体
]
#endif
如果启用 .showPhysics 后看不到碰撞形状,说明你的 缺失或配置错误。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
CollisionComponent节省时间 : 30-60 分钟 → 2-5 分钟
实体已添加但未显示
│
├─ 实体是否已添加到场景中?
│ └─ 否 → 添加到 RealityView 内容中:
│ content.add(entity)
│ ✓ 实体必须在场景图中才能渲染
│
├─ 实体是否有 ModelComponent?
│ └─ 否 → 添加网格和材质:
│ entity.components[ModelComponent.self] = ModelComponent(
│ mesh: .generateBox(size: 0.1),
│ materials: [SimpleMaterial(color: .red, isMetallic: false)]
│ )
│ ✓ 空的 Entity 是不可见的——它只是一个容器
│
├─ 实体的缩放比例是否为零或接近零?
│ └─ 检查 → 打印:entity.scale
│ USD 模型导入时可能带有意外的缩放比例。
│ 尝试:entity.scale = SIMD3(repeating: 0.01) 用于米级模型
│
├─ 实体是否在相机后面?
│ └─ 检查 → 打印:entity.position(relativeTo: nil)
│ 在 RealityKit 中,-Z 是向前(朝向屏幕)。
│ 尝试:entity.position = SIMD3(0, 0, -0.5) (前方半米处)
│
├─ 实体是否在另一个物体内部?
│ └─ 检查 → 移动到一个已知可见的位置:
│ entity.position = SIMD3(0, 0, -1)
│
├─ 实体的 isEnabled 是否设置为 false?
│ └─ 检查 → entity.isEnabled = true
│ 同时检查父级:entity.isEnabledInHierarchy
│
├─ 实体是否在未跟踪的锚点上?
│ └─ 检查 → 验证锚点是否正在跟踪:
│ entity.isAnchored (应为 true)
│ 如果使用平面锚点,请确保先检测到表面
│
└─ 材质是否透明或是 OcclusionMaterial?
└─ 检查 → 检查材质:
如果使用 PhysicallyBasedMaterial,检查 baseColor 是否为黑色
如果使用 blending = .transparent,检查 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)")
}
节省时间 : 20-45 分钟 → 3-5 分钟
AR 内容未出现或漂浮
│
├─ AR 会话是否正在运行?
│ └─ 对于 iOS 18+ 上的 RealityView,AR 会自动运行
│ 对于 ARView,检查:arView.session.isRunning
│
├─ SpatialTrackingSession 是否已配置?(iOS 18+)
│ └─ 检查 → 确保请求了跟踪模式:
│ let config = SpatialTrackingSession.Configuration(
│ tracking: [.plane, .object])
│ let result = await session.run(config)
│ if let notSupported = result {
│ // 处理不支持的模式
│ }
│
├─ 锚点类型是否适合环境?
│ ├─ .plane(.horizontal) → 需要相机可见的平坦表面
│ ├─ .plane(.vertical) → 需要相机可见的墙壁
│ ├─ .image → 图像必须在 "AR Resources" 资源目录中
│ ├─ .face → 需要前置摄像头(非后置)
│ └─ .body → 必须能看到全身
│
├─ minimumBounds 是否太大?
│ └─ 检查 → 减小最小边界:
│ AnchorEntity(.plane(.horizontal, classification: .any,
│ minimumBounds: SIMD2(0.1, 0.1))) // 更小 = 更快检测到
│
├─ 设备是否受支持?
│ └─ 检查 → 平面检测需要 A12+ 芯片
│ 面部跟踪需要 TrueDepth 摄像头
│ 身体跟踪需要 A12+ 芯片
│
└─ 环境是否合适?
└─ 检查 → AR 需要:
- 充足的光线(不能太暗)
- 有纹理的表面(不是空白墙壁)
- 初始检测期间设备位置稳定
节省时间 : 15-30 分钟 → 2-3 分钟
点击/拖拽实体无反应
│
├─ 实体是否有 CollisionComponent?
│ └─ 否 → 添加碰撞形状:
│ entity.generateCollisionShapes(recursive: true)
│ // 或手动:
│ entity.components[CollisionComponent.self] = CollisionComponent(
│ shapes: [.generateBox(size: SIMD3(0.1, 0.1, 0.1))])
│ ✓ 手势命中测试需要碰撞形状
│
├─ [visionOS] 实体是否有 InputTargetComponent?
│ └─ 否 → 添加它:
│ entity.components[InputTargetComponent.self] = InputTargetComponent()
│ ✓ visionOS 上需要此组件才能接收手势输入
│
├─ 手势是否附加到 RealityView?
│ └─ 检查 → 手势必须在视图上,而不是实体上:
│ RealityView { content in ... }
│ .gesture(TapGesture().targetedToAnyEntity().onEnded { ... })
│
├─ 碰撞形状是否足够大以便点击?
│ └─ 检查 → 启用 .showPhysics 查看形状
│ 形状太小 = 难以点击。
│ 尝试:.generateBox(size: SIMD3(repeating: 0.1)) 最小值
│
├─ 实体是否在另一个实体后面?
│ └─ 检查 → 前面的实体可能会阻挡后面实体的手势
│ 确保碰撞在预期的目标上
│
└─ 实体是否启用?
└─ 检查 → entity.isEnabled 必须为 true
禁用的实体不接收输入
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)")
}
}
节省时间 : 1-3 小时 → 10-20 分钟
帧率下降或卡顿
│
├─ 场景中有多少个实体?
│ └─ 检查 → 打印实体数量:
│ var count = 0
│ func countEntities(_ entity: Entity) {
│ count += 1
│ for child in entity.children { countEntities(child) }
│ }
│ 低于 100:不太可能是实体数量问题
│ 100-500:需要审查优化
│ 500+:肯定需要优化
│
├─ 网格/材质资源是否共享?
│ └─ 否 → 在相同的实体间共享资源:
│ let sharedMesh = MeshResource.generateBox(size: 0.05)
│ let sharedMaterial = SimpleMaterial(color: .white, isMetallic: false)
│ // 为所有实例复用
│ ✓ RealityKit 会批处理具有相同资源的实体
│
├─ 是否有 System 在每帧创建组件?
│ └─ 检查 → 在 update() 中查找分配:
│ 每帧创建 ModelComponent、CollisionComponent 或材质
│ 会导致 GC 压力。
│ 缓存资源,仅在值改变时更新。
│
├─ 碰撞形状是否基于网格?
│ └─ 检查 → 对于动态实体,将 generateCollisionShapes(recursive: true)
│ 替换为简单形状(box、sphere、capsule)
│
├─ generateCollisionShapes 是否被重复调用?
│ └─ 检查 → 在设置期间调用一次,而不是每帧都调用
│
├─ 物理体是否过多?
│ └─ 检查 → 动态体最昂贵。
│ 将远处的/静态的物体转换为 .static 模式。
│ 从非交互式实体中移除物理组件。
│
└─ 模型多边形数量是否过高?
└─ 检查 → 为实时使用简化模型。
目标:移动 AR 总三角形数 < 10 万。
对远处的物体使用 LOD(细节层次)。
节省时间 : 15-45 分钟 → 5-10 分钟
颜色、光照或纹理看起来不正确
│
├─ 场景是否太暗?
│ └─ 检查 → 缺少环境光照:
│ 添加 DirectionalLightComponent 或 EnvironmentResource
│ 在 AR 中,RealityKit 自动使用真实世界光照
│ 在非 AR 中,必须显式提供光照
│
├─ baseColor 是否已设置?
│ └─ 检查 → PhysicallyBasedMaterial 默认为白色
│ material.baseColor = .init(tint: .red)
│ 如果使用纹理,请验证它已加载:
│ try TextureResource(named: "albedo")
│
├─ metallic 是否设置不正确?
│ └─ 检查 → metallic = 1.0 使表面像镜子
│ 大多数真实物体:metallic = 0.0
│ 只有金属(金、银、铬):metallic = 1.0
│
├─ 纹理语义是否错误?
│ └─ 检查 → 使用正确的语义:
│ .color 用于反照率/baseColor 纹理
│ .raw 用于数据纹理(金属度、粗糙度)
│ .normal 用于法线贴图
│ .hdrColor 用于 HDR 纹理
│
├─ 模型是否上下颠倒或内外翻转?
│ └─ 检查 → 尝试:
│ material.faceCulling = .none (显示两面)
│ 如果这能解决问题,说明模型法线翻转了
│
└─ 混合/透明度是否出乎意料?
└─ 检查 → material.blending
默认是 .opaque
对于透明度:.transparent(opacity: ...)
节省时间 : 20-40 分钟 → 5-10 分钟
物体相互穿过或不碰撞
│
├─ 两个实体都有 CollisionComponent 吗?
│ └─ 否 → 碰撞的双方都需要 CollisionComponent
│
├─ 移动的实体有 PhysicsBodyComponent 吗?
│ └─ 否 → 添加物理体:
│ entity.components[PhysicsBodyComponent.self] = PhysicsBodyComponent(
│ mode: .dynamic)
│
├─ 碰撞组/过滤器配置正确吗?
│ └─ 检查 → 实体必须在兼容的组中:
│ 默认:group = .default, mask = .all
│ 如果使用自定义组,请验证 mask 包含另一个组
│
├─ 物理模式正确吗?
│ ├─ 两个 .static 体 → 永不碰撞(都不可移动)
│ ├─ .dynamic + .static → 正确(常见设置)
│ ├─ .dynamic + .dynamic → 碰撞时两者都移动
│ └─ .kinematic + .dynamic → Kinematic 推动 dynamic
│
├─ 碰撞形状合适吗?
│ └─ 检查 → .showPhysics 调试选项
│ 形状可能太小、偏移或类型错误
│
└─ 实体是否在不同的锚点上?
└─ 检查 → "物理体和碰撞器仅影响
共享同一锚点的实体"(Apple 文档)
将相互作用的实体放在同一锚点下
节省时间 : 30-60 分钟 → 10-15 分钟
实体未在其他设备上出现
│
├─ 实体有 SynchronizationComponent 吗?
│ └─ 否 → 添加它:
│ entity.components[SynchronizationComponent.self] =
│ SynchronizationComponent()
│
├─ MultipeerConnectivityService 设置好了吗?
│ └─ 检查 → 在同步前验证 MCSession 已连接
│
├─ 自定义组件是 Codable 的吗?
│ └─ 否 → 非 Codable 的组件不同步
│ struct MyComponent: Component, Codable { ... }
│
├─ 实体有所有者吗?
│ └─ 检查 → 只有所有者可以修改同步的属性
│ 在修改前请求所有权:
│ entity.requestOwnership { result in ... }
│
└─ 实体有锚点吗?
└─ 检查 → 未锚定的实体可能无法正确同步位置
使用共享的世界锚点进行可靠的定位
| 错误 | 耗时 | 修复方法 |
|---|---|---|
| 交互式实体没有 CollisionComponent | 15-30 分钟 | entity.generateCollisionShapes(recursive: true) |
| visionOS 上缺少 InputTargetComponent | 10-20 分钟 | 添加 InputTargetComponent() |
| 手势附加在错误的视图上(不是 RealityView) | 10-15 分钟 | 将 .gesture() 附加到 RealityView |
| USD 模型的实体缩放比例错误 | 15-30 分钟 | 检查单位:米 vs 厘米 |
| 非 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 小时 |
| 颜色错误 | 有光照吗?金属度值? | 15-45 分钟 |
| 无碰撞 | 双方都有 CollisionComponent 吗?同一锚点? | 20-40 分钟 |
| 不同步 | 有 SynchronizationComponent 吗?Codable? | 30-60 分钟 |
| 模拟器正常,设备崩溃 | Metal 功能?纹理格式? | 15-30 分钟 |
耗时 : 15-30 分钟(常被误诊为模型问题)
Q1: 崩溃是 Metal 错误吗(MTLCommandBuffer,着色器编译)?
├─ 是 → 模拟器使用软件渲染,设备使用真实 GPU
│ 常见原因:
│ - 自定义 Metal 着色器使用了设备不支持的功能
│ - 纹理格式在设备 GPU 上不受支持
│ - 超出设备纹理大小限制(旧设备最大 8192x8192)
│ 修复:检查设备 GPU 系列,使用支持的格式
│
└─ 否 → 检查下一个
Q2: 是内存不足崩溃吗?
├─ 是 → 模拟器有更多可用 RAM
│ 常见:带有未压缩纹理的大型 USDZ 文件
│ 修复:压缩纹理,减少多边形数量,使用 LOD
│ 检查:USDZ 文件大小(保持 < 50MB 以确保可靠加载)
│
└─ 否 → 检查下一个
Q3: 是 AR 相关崩溃吗(相机、跟踪)?
├─ 是 → 模拟器没有真实的相机/传感器
│ 修复:仅在设备上测试 AR 功能,使用模拟器进行 UI/布局测试
│
└─ 否 → 检查设备能力
- RealityKit 需要 A12+
- 场景重建需要 LiDAR
- 面部跟踪需要 TrueDepth
WWDC : 2019-603, 2019-605, 2023-10080, 2024-10103
文档 : /realitykit, /realitykit/entity, /realitykit/collisioncomponent, /realitykit/physicsbodycomponent
技能 : axiom-realitykit, axiom-realitykit-ref
每周安装次数
69
代码仓库
GitHub 星标数
601
首次出现
2026年2月5日
安全审计
安装于
opencode65
gemini-cli62
codex61
github-copilot60
kimi-cli59
cursor59
Systematic diagnosis for common RealityKit issues with time-cost annotations.
Use this skill when:
For RealityKit architecture patterns and best practices, see axiom-realitykit. For API reference, see axiom-realitykit-ref.
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.
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
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)")
}
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
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
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)")
}
}
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.
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: ...)
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
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
| 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 |
| 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 |
| Sim OK, device crash | Metal features? Texture format? | 15-30 min |
Time cost : 15-30 min (often misdiagnosed as model issue)
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
Docs : /realitykit, /realitykit/entity, /realitykit/collisioncomponent, /realitykit/physicsbodycomponent
Skills : axiom-realitykit, axiom-realitykit-ref
Weekly Installs
69
Repository
GitHub Stars
601
First Seen
Feb 5, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode65
gemini-cli62
codex61
github-copilot60
kimi-cli59
cursor59
App Store Connect 参考指南:崩溃分析、TestFlight反馈与性能指标导出
164 周安装
Nansen 聪明钱分析工具:追踪加密基金和顶级交易者持仓与交易数据
165 周安装
NSFC国家自然科学基金申请书研究内容写作工具 - LaTeX自动化编排助手
165 周安装
SOLID 原则详解:SRP、OCP、LSP 等设计模式,提升代码可维护性与灵活性
167 周安装
WordPress全站编辑(FSE)与区块编辑器指南:theme.json配置与站点编辑器实战
171 周安装
A轮以上初创公司获客指南:PLG与销售驱动混合模式下的需求生成与SEO策略
166 周安装
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 |