我观察到一个非常奇怪的行为,复制的 SCNGeometry 不能立即工作。我必须等待一个运行循环(
DispatchQueue.main.async
)才能使其工作。这是一个错误还是我做错了什么?
这是我的代码:
func helper_cloneGeo(geo: SCNGeometry) -> SCNGeometry {
let copiedGeo = geo.copy() as! SCNGeometry
copiedGeo.materials = geo.materials.map { $0.copy() as! SCNMaterial }
return copiedGeo
}
override init() {
super.init()
let geo = readGeo(fn: "alcohol.usdz", texture: "texture.png").geometry!
// HERE!!!
// SCNGeometry is only clone-able after async!!
// DispatchQueue.main.async {
let copiedGeo = self.helper_cloneGeo(geo: geo)
let newNode = SCNNode(geometry: copiedGeo)
self.rootNode.addChildNode(newNode)
// }
}
readGeo
只是一个读取 3D 模型文件的辅助函数,这应该是正确的,因为原始(非克隆)节点可以工作。
您可以在此处下载我的示例项目:https://drive.google.com/file/d/1kYyqCAJXnXqpZc6vaaXORe_UVmLH6wHL/view?usp=sharing
在这个项目中,当你运行它时,它会显示模型。然后,如果您注释掉
DispatchQueue.main.async
(如上面的代码),模型将不会显示。
通过进行一些基本的调试,您可以看到
geo.elements
和 geo.sources
都是空的,这就是为什么没有复制任何内容。我怀疑 SCNNode.flattenedClone
(您在 readGeo
中使用的)以某种方式创建了一个具有“惰性”几何形状的节点,该几何形状不会立即创建。
如果您不想异步执行此操作,您始终可以自己运行运行循环。
let geo = readGeo(fn: "alcohol.usdz", texture: "texture.png").geometry!
RunLoop.main.run(until: .now) // run the run loop for just one iteration
let copiedGeo = self.helper_cloneGeo(geo: geo)
let newNode = SCNNode(geometry: copiedGeo)