iOS AR开发:如何获取自定义USD场景的父ModelEntity?
解决自定义USD模型导入后无法获取ModelEntity的问题
问题分析
使用Xcode标准Box场景时,可通过指定名称simpBld_root找到ModelEntity,但导入自定义USD模型后,直接用控制台显示的“USD scene”查找失败,核心原因是自定义USD的实体层级与标准Box不同,且“USD scene”并非实体的真实name属性值。
解决方案
1. 排查实体层级与真实名称
加载自定义USD锚点后,枚举并打印所有实体的名称和类型,明确目标实体的真实名称:
usdAnchor.enumerateEntities { entity, stop in print("实体名称:\(entity.name),类型:\(type(of: entity))") }
运行代码后查看控制台输出,即可找到自定义USD根实体的真实名称(而非控制台显示的“USD scene”)。
2. 两种方式获取目标ModelEntity
方式一:直接获取锚点的第一个子实体
自定义USD导入后,锚点的第一个子实体通常就是模型的根节点,可直接获取:
if let usdRoot = usdAnchor.children.first as? GstReady { // 递归生成碰撞体(适配USD模型的多层级结构) usdRoot.generateCollisionShapes(recursive: true) // 安装交互手势 arView.installGestures([.rotation, .scale, .translation], for: usdRoot) }
方式二:通过真实名称查找
根据步骤1打印出的真实名称,使用findEntity(named:)精准查找:
if let usdRoot = usdAnchor.findEntity(named: "你的USD根实体真实名称") as? GstReady { usdRoot.generateCollisionShapes(recursive: true) arView.installGestures([.rotation, .scale, .translation], for: usdRoot) }
修改后的完整代码示例
import SwiftUI import RealityKit struct ContentView : View { var body: some View { ARViewContainer().edgesIgnoringSafeArea(.all) } } struct ARViewContainer: UIViewRepresentable { func makeUIView(context: Context) -> ARView { let arView = ARView(frame: .zero) typealias GstReady = Entity & HasCollision // 替换为你自定义USD对应的load方法(导入后RealityKit自动生成) let usdAnchor = try! Experience2.loadCustomUSD() arView.scene.anchors.append(usdAnchor) // 打印所有实体,排查层级与名称 usdAnchor.enumerateEntities { entity, stop in print("实体名称:\(entity.name),类型:\(type(of: entity))") } // 方式一:获取第一个子实体 if let usdRoot = usdAnchor.children.first as? GstReady { usdRoot.generateCollisionShapes(recursive: true) arView.installGestures([.rotation, .scale, .translation], for: usdRoot) } // 方式二:根据真实名称查找(注释方式一,打开此注释即可) // if let usdRoot = usdAnchor.findEntity(named: "USD根实体真实名称") as? GstReady { // usdRoot.generateCollisionShapes(recursive: true) // arView.installGestures([.rotation, .scale, .translation], for: usdRoot) // } return arView } func updateUIView(_ uiView: ARView, context: Context) {} } #if DEBUG struct ContentView_Previews : PreviewProvider { static var previews: some View { ContentView() } } #endif
注意事项
- 确保自定义USD已正确导入到RealityKit项目中,生成对应的
loadXXX()方法(可在Experience2.swift中查看)。 - 使用
generateCollisionShapes(recursive: true):若USD模型包含多层级子实体,递归生成碰撞体才能让手势作用于整个模型。 - 不要依赖控制台显示的“USD scene”作为查找名称,必须通过枚举实体获取真实的
name属性值。
内容的提问来源于stack exchange,提问作者Remy Konings
相关产品推荐
相关产品推荐

