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!
Try this (assuming you are using Swift):
rootNode.enumerateChildNodes { (node, stop) in
node.removeFromParentNode()
}
Works for me.
For me worked like below:
sceneView.scene.rootNode.enumerateChildNodes { (node, stop) in
node.removeFromParentNode() }
you can either create a new scene or call -[SCNNode removeFromParentNode] on every child node of the scene's rootNode
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!
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];
}
Modifying a collection while looping through it is not good practice; here's an alternative:
while let n = node.childNodes.first { n.removeFromParentNode() }
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
Related
So this may seem like a stupid question; however, I'll see if anyone has an answer.
Is there any way to change the color of all nodes in a scene in swift? For example invert all the colors?
I've created a game using SpriteKit and would like to create different themes. Instead of changing every node one by one. I would like to at least do most in one shot. If anyone has any advice that would be greatly appreciated! Thanks!
-Matt
Inside of the scene you want,
for node in self.children {
// I used spritenode, but you can add as many nodes with color options as you like.
guard let snode = node as? SKSpriteNode else { continue }
snode.color = .blue
}
The inversion function would be a separate question I think :P but something like:
if snode.color == .black { node.color == .white }
But you could probably do this with RGB and math as well.
Im trying to see when my circleGroup Class Object has left the screen
(am pretty new at this so any suggestions welcome!)
including any other way to remove the class once it is off screen
circleGroup Class contains a blank SKSpriteNode, and 8 other sprites are grouped around the blank SKSpriteNode as children (these have physics),
Gamelayer:
Always logs (0,0)
NSLog(#"_mycircleGroup.position.y #%f",_mycircleGroup.position.y);
//outputs myArc.position.y #0.000000
which means I can't check when Class is off screen
if (_mycircleGroup.position.y < 0)
{
NSLog(#"_mycircleGroup off screen");
//[_mycircleGroup removeFromParent];
//[self myMethod];
}
Any ideas how I might read position?
with thanks
:)
Solution,
I needed to be logging the parent node inside of the class
so in this case I have a class and in it is a parent sprite which i need to track (Since it seems like nodes with physics don't track)
if (self.myCircleClass.parentSpriteThatEveryThingIsAddedTo.position.y < 0)
{
NSLog(#"my arc off screen");
//[twoSpritesWithParticlesBridge removeFromParent];
//[self addStaticLinkedSpriteWithParticles];
}
As above with thanks to WangYudong for jogging my logic :P
Solution, I needed to be logging the parent node inside of the Class so in this case I have a class and in it is a parent sprite which I need to track (Since it seems like nodes with physics don't track, so I couldn't track te entire object, just the object without physics...)
if (self.myCircleClass.parentSpriteThatAllOtherSpritesParentedTo.position.y < 0)
{
NSLog(#"my arc off screen");
//[twoSpritesWithParticlesBridge removeFromParent];
//[self addStaticLinkedSpriteWithParticles];
}
Take everything with a pinch of salt, non definite and completely questionable! (since I'm new at coding), but hope it helps someone :)
I'm trying to remove some nodes from a parent node once they reach a certain x position. The problem I have is that the parent node is changing x position, but the children are not changing x position inside the parent (but are obviously moving with the parent), so when I put in if node.position.x < 300 . . . (remove node), nothing happens. I tried the below code, but this only work one time and then doesn't remove nodes again, which I'm not 100% sure why it stops working.
func cleanUp() {
let positionX = nodeBase.position.x
nodeBase.enumerateChildNodesWithName("segment", usingBlock: {
node, stop in
if node.position.x - positionX < 300 {
node.removeFromParent()
}
})
}
Can anybody see where I am going wrong with my code, or can you point me in the right direction?
Try the following:
nodeBase.enumerateChildNodesWithName("segment") { node, _ in
if !self.intersectsNode(node) {
node.removeFromParent()
}
}
intersectsNode returns true whilst the node is inside the bounds of SKScene. Therefore, when intersectsNode returns false you know the node is offscreen and you can remove the node.
I found some other questions about node removal in swift, but none of them seemed to be quite relevant to my issue.
I just want to do a basic node removal, for example:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent){
let covernode1 = SKSpriteNode(imageNamed: "tester")
covernode1.position = CGPointMake(100.0, 600.0)
for touch: AnyObject in touches {
if self.nodeAtPoint(location) == self.fake {
button1++
button2++
}
if(button1 == 1 && button2 == 1){
addChild(covernode1)
}
if(button1 == 2 && button2 == 2){
//THIS IS WHERE I WANT TO REMOVE THE NODE
}
I have tried
covernode1.removeFromParent()
but to no avail.
The code runs the addChild part fine, but removal seems to be a problem. I even tried just changing the position of the node so it's off screen, with something like
covernode1.position = CGPointMake(-100.0, -600.0)
This did not work either.
Thank you.
Unfortunately I don't have enough reputation to comment on your original question, so this may not be an "answer" per se, but I'll try and diagnose what I think is going on, and hopefully you can clear up some points for me.
The covernode1 that you are trying to remove from the parent view in your if statement may be a different node than the one you added to the view when you called addChild(covernode1)
I think this is the case because when you say you are using covernode1.position = CGPointMake(-100.0, -600.0) and it still does not work, that makes me think that is a completely different SKNode object.
Instead, try declaring covernode1 outside of the function as a class variable. That way, when you actually instantiate it and refer to it in the function, it is grabbing the correct node you are looking for. Let me know if any of this helps. I'll edit the answer when I know a bit more from your response.
Also, are your button1 and button2 vars originally set to 1?
EDIT: Another question: Are you receiving any error when calling .removeFromParent() or is just "not doing anything"?
One simple thing you could do (kind of cheating but it will work) is to hide the node using
covernode1.hidden = true
Note
Also make sure the if statement actually runs because I don't know why the things you tried should not work. To test that, place a println("log") in the if block.
Hope that helps :)
From button1 and button2, I think you are trying to do this: On the first click, you add a SKNode. On the second click, you want to remove the SKNode.
Thus on the second click your let covernode1 = SKSpriteNode(imageNamed: "tester") is a different instance although it has the same variable name ! Thus the instance on the second click is not removable since it was not added to anything.
Try this,
if(button1 == 1 && button2 == 1){
addChild(covernode1)
self.tempChildCount = count(self.children) //tempChildCount is an integer
}
if(button1 == 2 && button2 == 2){
let childNode = self.children[self.tempChildCount - 1 ] as! SKNode
self.removeChildrenInArray([childNode])
}
What do you recommend me if I have two layers (which are added to a parallaxNode) and on each layers I've added sprites which I want to restrict the order that the player won't be able to remove sprite5 until it removes first the previous ones: sprite1, sprite2, sprite3 and sprite4 and so one.
I'm using Juan's example for dynamically touch detection
What will be the dynamical option for this?
UPDATE:
if([sprite tag] == tag_collection_1 && [sprite GetCanTrack]) {
//Set others to NO & call remove sprite method
[[TSprite FindByTag:tag_collection_number] SetCanTrack:NO];
[self removeSpriteMethod:touchLocation];
} else if ([sprite tag] == tag_collection_number && [sprite GetCanTrack]) {
// and so on
}
Use a fifo stack implementation. If you want to remove the sprite, you first check if it's at the bottom of the stack and when you do remove it, you pop it from the stack as well. Practically you will have an NSMutableArray and look at the first item if the object is in that position before you remove it. If you have added 1,2,3,4,5 in that order and want only to be able to remove them in the same order you check if the object you are trying to remove is at index 0 in the array first.