SceneKit - 线程 - 在哪个线程上执行什么操作?

19

在使用SceneKit时,update方法:

func renderer(aRenderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval)    

该方法不在主线程上被调用,而是在其他线程上调用。

我应该在主线程上做什么?在这个“SceneKit线程”上应该做什么?

我应该在哪里添加新的节点/几何体?

修改这些对象的位置/等属性在哪里是安全的?


这可能是由于GameKit的组件建模/循环被赋予主线程以获得DOD效率的结果吗? - Confused
我不确定,目前我认为他们只是将所有SceneKit的东西从主线程中移开了,如果你想改变任何重要的东西,你必须去到主线程。 - Max
注意:我偶尔会在主线程上调用此方法。现在我的应用程序已经暂停在为此目的设置的断点处(在Thread.isMainThread测试中),并且调试导航器正在显示此内容。在Xcode 8上运行iOS 10.2模拟器。我猜这是一个SceneKit的错误。似乎第一次调用时会有几个百分点的概率发生。 - DenverCoder9
嗯,我已经很久没有使用SceneKit了,而且很可能不会再次使用它,因为存在太多问题。但也许你可以尝试添加一个打印语句并查看它打印的内容 - 调试导航器有时会显示错误的信息。 - keyboard
2个回答

11

这个问题涉及到Scenekit。即使您的操作是在主线程上进行的,节点/几何体实际上并没有被添加到主线程上。Scenekit不会在主线程上渲染。更改将被批处理到渲染线程。如果渲染是UI,那么它就不在主线程上。实际上,如果您在主线程上进行更改,则会收到错误的例外,因为渲染线程正在尝试渲染被删除的对象。这就是为什么在苹果香蕉游戏中,removefromparent位于SCNTransaction中的原因。因此,移除操作发生在渲染线程而不是主线程上。添加操作也以同样的方式批处理。它实际上并没有添加到主线程上。

因此,请注意同时存在一个渲染线程。如果您在主线程上对场景的rootnode进行枚举操作,您将从渲染线程中得到根节点的更改导致的崩溃。但由于事情发生得如此之快,所以这种情况可能相当罕见。总的来说,去查看香蕉游戏、狐狸游戏等,并了解它们如何使用。


6
SCNSceneRendererDelegate的文档在此处在此处似乎对线程没有任何说明,但是代理显然在辅助线程上调用,至少在macOS 10.11.6上(以及您所在的任何iOS版本)。如果这对SceneKit造成任何问题,我们可以合理地假设,该文档将通过现在进行修订。
苹果的Fox示例代码具有渲染器代理,它对场景进行了许多更改,似乎不考虑其他线程可能会做什么,并且从这个示例代码中,人们可以合理地认为这样做对SceneKit没有任何问题。 (看起来Fox几乎完全由渲染器代理驱动,因此它可能很少需要担心多个线程。)
这可能是由于SceneKit的自动每线程事务,在此处记录。听起来,只要您在返回运行循环之前不需要可见效果,您可以随时做任何想做的事情。这是我能找到的唯一一篇以实质性方式提到线程的SceneKit文档。
以上所有内容都说了,这可能对您自己的逻辑来说是一个巨大的问题。好消息是您注意到代理在辅助线程上调用。如果您在项目早期没有及时注意到这一点,则坏消息是您可能有很多工作要做。
线程可以通过各种方式进行同步。您最好使用苹果的现代设施来实现这一点,但是如果您发现自己处于困境中,也有其他各种旧方法可以考虑。

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