When using SceneKit, the update method:
func renderer(aRenderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval)
is not called on the main thead, but on some other thread.
What am I supposed to do on the main thread, and what has to be done on this "SceneKit thread"?
Where should I add new nodes / geometry?
Where is it safe to modify position / etc of these objects?
The question is about scenekit. Nodes/geometry aren't actually added on the main thread even if that's where you do it. Scenekit does not render on the main thread. Changes are batched to the rendering thread. If rendering is the UI, it's not on the main thread. In fact, if you make changes on the main thread you'll get bad exc because the rendering thread is trying to render the object that got nuked. Which is why removefromparent is inside a SCNTransaction in Apples banana game. So the removal happens on the rendering thread not the main thread. Adding gets batched the same way. It's not actually added on the main thread.
So just be aware that there's a rendering thread going at the same time. If you do an enumerate with the scene.rootnode on the main thread you'll get crashes from the rendering thread making changes to the rootnode. But since things happen so fast it will probably be pretty rare. In general go check out the banana game, the fox game, and see how they use it.
The documentation for SCNSceneRendererDelegate here and here seems to have nothing to say about threads, and yet the delegate is clearly invoked on a secondary thread, at least on macOS 10.11.6 (and apparently whatever version of iOS you are on). One might reasonably suppose that if this had posed any kind of issue for SceneKit the documentation would by now have been revised accordingly.
Apple's Fox sample code has a renderer delegate which makes many changes to the scene seemingly without regard to what any other thread might be up to, and from this one might reasonably assume that doing so poses no issue for SceneKit. (It also seems as if Fox is driven almost entirely out of the renderer delegate, so perhaps it has little reason to worry about multiple threads.)
This may be possible due to SceneKit's automatic per-thread transactions as documented here. It sounds as if you can do whatever you want whenever you want as long as you don't require visible effects any earlier than your return to the run loop. This is the only documentation I could find about SceneKit that mentions threads in any substantive way.
The above all said, this could be a huge issue for your own logic. The good news is that you noticed your delegate is being invoked on a secondary thread. If you didn't notice this early in your project, the bad news is you might have a lot of work to do.
Threads may be synchronized in a variety of ways. You're probably best off using Apple's modern facilities for doing so, but there is also a variety of other, older approaches you may want to consider if you find yourself in a tight spot.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With