SceneKit:如何在运行时从其他场景加载节点?

4

我有一个主场景文件:main.scn,以及其他几个包含额外SCN节点的场景文件:scene1.scnscene2.scnscene3.scn等。在应用程序启动时,我从scene1.scn中加载所需节点,并将它们添加到main.scn中(显示在屏幕上)。在运行时,我需要从其他sceneN.scn文件中添加附加节点。我尝试过两种方法,但都没有使用:

1)renderer(_,updateAtTime)内部,我只需加载所需节点:

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    let scene2 = SCNScene(named: "game.scnassets/scene2.scn")!
    let node = scene2.rootNode.childNode(withName: "nodeName", recursively: false)!
    mainScene.rootNode.addChildNode(node)
}

在这种情况下,我会得到错误信息: [SceneKit] Error: Scene is modified within a rendering callback of another scene (). This is not allowed and may lead to crash 2) 在后台加载场景2和节点,将其添加到一些 nodesToShow 数组中,并在 renderer(_, updateAtTime) 中显示数组中的节点。在这种情况下,有时会出现以下错误: com.apple.scenekit.scnview-renderer (17): EXC_BAD_ACCESS (code=1, address=0xf000000010a10c10) 也许您知道一些真正的解决方案来在运行时加载和展示其他场景文件中的节点?
1个回答

7
您可以使用 SCNReferenceNode 来加载另一个场景文件中的内容:

场景图节点,用作从单独的场景文件加载内容的占位符。

然后,您应该将 .load() 命令包含在 SCNTransaction 块中以创建原子更新:

此事务将任何其他更改组合在一起,这些更改是在当前线程的运行循环的当前迭代期间从同一线程进行的。当运行循环下次迭代时,SceneKit 自动提交此事务,将事务期间进行的所有更改以原子方式应用于演示场景图(即当前正在显示的场景图版本)。

Swift 代码:
let url = Bundle.main.url(forResource: "ship", withExtension: "scn", subdirectory: "art.scnassets")!
let referenceNode = SCNReferenceNode(url: url)!
scnView.scene!.rootNode.addChildNode(referenceNode)
SCNTransaction.begin()
referenceNode.load()
SCNTransaction.commit()

如果我在 renderer(_, updateAtTime) 中执行代码,会出现错误:[SceneKit] Error: Scene is modified within a rendering callback of another scene (). This is not allowed and may lead to crash。 - Sergey Didanov
没有 .load(),屏幕上没有节点也没有错误。 - Sergey Didanov
1
我已经编辑了答案。如果你把.load()命令放在一个SCNTransaction块中,错误就会消失。 - MasDennis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接