I traced a major performance bottleneck in my SceneKit app to a nested loop being run a few thousand times. In that loop is a bunch of code that zooms along quite happily, apart from this one line:
var scenePos = presentation.position
It's over 100 times slower than just asking for the position PLUS dozens of other calculations, comparisons, array lookups & method calls combined that I was doing inside the same loop. I'm surprised no-one seems to have commented on this yet that I can find.
Why is this, and is there a workaround for it apart from making a copy of each node's presentation.position yourself each frame so you don't have to keep asking the presentation node for it? Thanks.
Edits: presentation.position is only ever being read, never written to. No boundingBox is ever edited. I'm using a dynamic SCNPhysicsBody for a few of the SCNNodes, but the vast majority are static.
Here's the workaround I'm currently using (for this, and also the separate issue that presentation.position can be zero if physics has never been run for that node). It's orders of magnitude faster, as nearly all my nodes are not dynamic.
// When you're not sure if physics has first run yet
func currentScenePos() -> SCNVector3 {
if physicsBody?.type == .dynamic {
var scenePos = presentation.position
if scenePos.isZero() {
// Looks like the physics hasn't run on this node yet. Use the regular position.
// If that's zero too, it must really be at the scene origin.
scenePos = position
}
return scenePos
} else {
// Non-dynamic physics. Just use position, it's a lot faster.
return position
}
}
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