Tim Andrews
Tim Andrews

Reputation: 847

How can I remove all nodes from a scenekit scene?

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!

Upvotes: 20

Views: 20281

Answers (8)

Nikandr Marhal
Nikandr Marhal

Reputation: 1470

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.

Upvotes: 2

user149533
user149533

Reputation:

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

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

Upvotes: 2

Hecot
Hecot

Reputation: 129

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];
}

Upvotes: 0

Alessandro Mattiuzzi
Alessandro Mattiuzzi

Reputation: 2467

For me worked like below:

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

Upvotes: 16

Alan
Alan

Reputation: 466

Try this (assuming you are using Swift):

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

Works for me.

Upvotes: 41

Jason
Jason

Reputation: 93

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

Upvotes: -1

DDPWNAGE
DDPWNAGE

Reputation: 1443

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!

Upvotes: 3

mnuages
mnuages

Reputation: 13462

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

Upvotes: 3

Related Questions