Eitan
Eitan

Reputation: 423

Find out when SCNNode disappears from SCNScene

Does a particular method get called when an SCNNode is removed from the scene?

-(void)removeFromParentNode;

Does not get called on the SCNNode object.

To set the scene

I am using gravity to pull down an object. When an object goes too far down, it automatically disappears and the draw calls and polygon counts decrease. So the SCNNode is definitely being destroyed, but is there a way I could hook into the destruction?

Upvotes: 1

Views: 1782

Answers (2)

rickster
rickster

Reputation: 126107

Other answers covered this pretty well already, but to go a bit further:

First, your node isn't being removed from the scene — its content is passing outside the camera's viewing frustum, which means SceneKit knows it doesn't need to issue draw calls to the GPU to render it. If you enumerate the child nodes of the scene (or of whatever parent contains the nodes you're talking about), you'll see that they're still there. You lose some of the rendering performance cost because SceneKit doesn't need to issue draw calls for stuff that it knows won't be visible in the frame.

(As noted in Tanguy's answer, this may be because of your zFar setting. Or it may not — it depends which direction the nodes are falling out of camera in.)

But if you keep adding nodes and letting physics drop them off the screen, you'll accumulate a pre-render performance cost, as SceneKit has to walk the scene graph every frame and figure out which nodes it'll need to issue draw calls for. This cost is pretty small for each node, but it could eventually add up to something you don't want to deal with.

And since you want to have something happen when the node falls out of frame anyway, you just need to find a good opportunity to both deal with that and clean up the disappearing node.

So where to do that? Well, you have a few options. As has been noted, you could put something into the render loop to check the visibility of every node on every frame:

- (void)renderer:(id<SCNSceneRenderer>)renderer didSimulatePhysicsAtTime:(NSTimeInterval)time {
    if (![renderer isNodeInsideFrustum:myNode withPointOfView:renderer.pointOfView]) {
        // it's gone, remove it from scene
    }
}

But that's a somewhat expensive check to be running on every frame (remember, you're targeting 30 or 60 fps here). A better way might be to let the physics system help you:

  1. Create a node with an SCNBox geometry that's big enough to "catch" everything that falls off the screen.
  2. Give that node a static physics body, and set up the category and collision bit masks so that your falling nodes will collide with it.
  3. Position that node just outside of the viewing frustum so that your falling objects hit it soon after they fall out of view.
  4. Implement a contact delegate method to destroy the falling nodes:

    - (void)physicsWorld:(SCNPhysicsWorld *)world didBeginContact:(SCNPhysicsContact *)contact {
        if (/* sort out which node is which */) {
            [fallingNode removeFromParentNode];
            // ... and do whatever else you want to do when it falls offscreen.
        }
    }
    

Upvotes: 3

Tanguy
Tanguy

Reputation: 984

Your object will disappear if it goes further than the ZFar property of your active camera. (default value is 100.0) As said by David Rönnqvist in comments, your Node is not destroyed and you can still modify its property.

If you want to hook-up to your Node's geometry disappearance, you can calculate the distance between your active camera and your Node and check it every frame in your rendering loop to trigger an action if it gets higher than 100.

If you want to render your Node at a greater distance, you can just modify the ZFar property of your camera.

Upvotes: 1

Related Questions