20

Hi I am trying to remove all nodes from my Scenekit scene but I cannot for the life of me figure out a way.

It seems logical to me that there must be a function for doing this automatically but I cannot find it.

In context, I am trying to remove all nodes so I can reset my scene, which will happen reasonably often. Perhaps there is another way of doing this and I would be fine with that, I'm not stuck with having to remove all nodes.

Thanks!

8 Answers 8

41

Try this (assuming you are using Swift):

rootNode.enumerateChildNodes { (node, stop) in
        node.removeFromParentNode()
    }

Works for me.

1
  • 2
    Note that per the Cocoa conventions it is a programmer error to mutate a collection (the child nodes) while it's being enumerated. I would not recommend doing that.
    – mnuages
    Commented Sep 10, 2019 at 12:27
15

For me worked like below:

sceneView.scene.rootNode.enumerateChildNodes { (node, stop) in
node.removeFromParentNode() }
1
  • Also you can skip pausing the session
    – kavehmb
    Commented Jan 11, 2018 at 22:08
3

you can either create a new scene or call -[SCNNode removeFromParentNode] on every child node of the scene's rootNode

1
  • I moved my accepted answer from this to Alans answer, partly because his is clearer but mostly because it is in swift which is what I tagged the question with. Commented Sep 5, 2019 at 5:15
3

Where you need to remove all of your nodes, call this (if your scene isn't self, change it):

for (SCNNode *node in [self children]) {
    [node removeFromParent]
}

Additionally, if you need to remove each node except for some, call this (say, we don't want to remove 3 nodes, and they're named a, b, and c)

for (SCNNode *node in [self children]) {
    if (![node.name isEqualToString:@"a"] && ![node.name isEqualToString:@"b"] && ![node.name isEqualToString:@"c"]) {
        [node removeFromParent]
    }
}

Hope this helps!

2

Modifying a collection while looping through it is not good practice; here's an alternative:

while let n = node.childNodes.first { n.removeFromParentNode() }
0
2

For some reason, every single answer on the topic I could find features SCNNode.enumerateChildNodes method, but using it has a significant downside — it is asynchronous. Meaning you could not be notified when all of node's children had been removed.

Fortunately, there is much more robust approach which takes advantage of childNodes(passingTest:) method. It basically allows you to retrieve all nodes that satisfy a condition, synchronously.

So removal of all child nodes could be achieved in two steps:

// baseNode: SCNNode is defined somewhere in your code

// 1. retrieve all child nodes
let allChildNodes = baseNode.childNodes { _, _ in true }

// 2. remove nodes from their parent
for childNode in allChildNodes {
  childNode.removeFromParentNode()
}

Note that we could use the first param of the block for more advanced filtering — say selecting nodes by their name, contents etc.

0

Here is a solution in Objective-C (Yes it still exists!)

while (self.sceneView.scene.rootNode.childNodes.count) {
    NSArray<SCNNode *> *nodes = self.sceneView.scene.rootNode.childNodes;
    [nodes[0] removeFromParentNode];
}
-1

the simplest way I found to remove all nodes from a scene is:

  self.removeAllChildren()

This worked well for me in XCode version 7.2

2
  • 3
    This method is not available in SceneKit nowadays Commented Jan 19, 2017 at 19:02
  • 1
    Because this is not a SceneKit but a SpriteKit method
    – user187676
    Commented Mar 29, 2018 at 12:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.