SpriteKit: find all descendants of SKNode of a particular class?
This question shows how to find all children of SKNode belonging to a specific class, but what if we want all descendants (such as grandchildren) belonging to a specific class?
Is there a native way to do this in SpriteKit or is this the only way to create a recursive solution form from the above question?
The SKNode documentation highlights a search function that allows you to find descendants with a specific name, but is there a way to filter descendants by class and not be named? We don't want to assign names to nodes if they can be avoided.
We are using Swift 3.
source to share
What we did was pass a block to the SKNode function, which finds the nodes by name, and used it *
as a search term to avoid naming the desired nodes.
var descendants = [CustomClass]()
nodeToSearch.enumerateChildNodes(withName: ".//*") { node, stop in
if node is CustomClass {
descendants.append(node as! CustomClass)
}
}
source to share
Just add this extension to your project
import SpriteKit
extension SKNode {
func allDescendants<Element: SKNode>(byType type: Element.Type) -> [Element] {
let currentLevel:[Element] = children.flatMap { $0 as? Element }
let moreLevels:[Element] = children.reduce([Element]()) { $0 + $1.allDescendants(byType: type) }
return currentLevel + moreLevels
}
}
Now you can get all descendants of a SKNode
specific type (for example SKSpriteNode
) by writing
let descendants = node.allDescendants(byType: SKSpriteNode.self)
Example
class Enemy: SKSpriteNode { }
let root = SKNode()
let a = Enemy()
let b = SKNode()
let c = SKNode()
let d = Enemy()
root.addChild(a)
root.addChild(b)
a.addChild(c)
a.addChild(d)
let enemies: [Enemy] = root.allDescendants(byType: Enemy.self)
print(enemies.count) // 2
source to share