You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blender导入模型的Cylinder添加Collision Component后碰撞无效

问题

导入包含平面(Plane)和圆柱体(Cylinders)的Blender模型后,尝试为圆柱体添加碰撞组件,但碰撞功能未生效。已确认模型及子实体结构打印正常,实体结构如下:

▿ '/' : Entity, children: 1
  ⟐ Transform
  ⟐ SynchronizationComponent
  ▿ 'cilinders' : Entity, children: 6
    ⟐ Transform
    ⟐ SynchronizationComponent
    ▿ 'Light' : Entity
      ⟐ Transform
      ⟐ SynchronizationComponent
    ▿ 'Camera' : Entity
      ⟐ Transform
      ⟐ SynchronizationComponent
    ▿ 'Plane' : Entity, children: 1
      ⟐ Transform
      ⟐ SynchronizationComponent
      ▿ 'Plane_geometry' : ModelEntity
        ⟐ Transform
        ⟐ ModelComponent
        ⟐ SynchronizationComponent
    ▿ 'Cylinder' : Entity, children: 1
      ⟐ Transform
      ⟐ SynchronizationComponent
      ▿ 'Cylinder_geometry' : ModelEntity
        ⟐ Transform
        ⟐ ModelComponent
        ⟐ SynchronizationComponent
    ▿ 'Cylinder_001' : Entity, children: 1
      ⟐ Transform
      ⟐ SynchronizationComponent
      ▿ 'Cylinder_001_geometry' : ModelEntity
        ⟐ Transform
        ⟐ ModelComponent
        ⟐ SynchronizationComponent
    ▿ 'Cylinder_002' : Entity, children: 1
      ⟐ Transform
      ⟐ SynchronizationComponent
      ▿ 'Cylinder_002_geometry' : ModelEntity
        ⟐ Transform
        ⟐ ModelComponent
        ⟐ SynchronizationComponent

已编写以下代码为单个圆柱体添加碰撞并订阅碰撞事件,但无效果:

let cylinder1 = importModel.children[0].children[3].children[0] as! ModelEntity
cylinder1.generateCollisionShapes(recursive: false)
DispatchQueue.main.async {
    arView.scene.subscribe(to: CollisionEvents.Began.self,
                           on: cylinder1) { _ in
        print("Collision ball detected!")

    }.store(in: &self.subscriptions)  
}
修复方案

以下是你遗漏的关键环节及修复方法:

  • 碰撞双方都需具备碰撞组件:碰撞事件触发的前提是两个交互实体都拥有CollisionComponent。如果是和虚拟物体(比如测试用的小球)碰撞,要给该物体也生成碰撞形状;如果是和AR场景中的真实平面交互,需确认ARPlaneAnchor对应的实体已开启碰撞。

  • 检查碰撞掩码匹配性:默认生成的碰撞掩码可能和目标实体不匹配,导致事件无法触发。手动设置掩码确保双方兼容:

    cylinder1.collision?.filter.group = .all
    cylinder1.collision?.filter.mask = .all
    
  • 替换硬索引的实体获取方式:importModel.children[0].children[3].children[0]这种硬编码索引极易因模型结构变动出错,建议通过名称递归查找实体:

    func findModelEntity(named targetName: String, in entity: Entity) -> ModelEntity? {
        if let modelEntity = entity as? ModelEntity, modelEntity.name == targetName {
            return modelEntity
        }
        for child in entity.children {
            if let found = findModelEntity(named: targetName, in: child) {
                return found
            }
        }
        return nil
    }
    
    // 使用示例
    if let cylinder1 = findModelEntity(named: "Cylinder_geometry", in: importModel) {
        cylinder1.generateCollisionShapes(recursive: false)
        // 后续设置掩码、订阅事件
    }
    
  • 确认事件订阅时机:必须在实体被添加到ARView场景后再订阅碰撞事件,否则无法接收回调。建议在模型导入完成并加入场景后执行订阅逻辑。

  • 调整碰撞形状生成参数:如果圆柱体模型包含子网格,recursive: false可能无法生成完整的碰撞形状,尝试改为recursive: true:

    cylinder1.generateCollisionShapes(recursive: true)
    

内容的提问来源于stack exchange,提问作者saro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 16:15:43