SpriteKit 獲取SKrefenceNode中的自定義類
阿新 • • 發佈:2022-05-28
解析
假設有一個 Cat.sks檔案,其場景編輯器的元素結構為
Scene (name = cat_scene)
-SKSPriteNode (name = cat_sprite)
當主場景檔案對其進行引用,其場景編輯器的元素結構為
Scene
-SKEditorReferenceNode (name = refCat ,引用了Cat.sks)
執行起來後,其實際的介面結構為
Scene -SKReferenceNode (name = refCat) --SKNode (name = null) ---SKSPriteNode (name = cat_sprite)【這裡是Cat.sks 的內容】
可見,SKReferenceNode直接提取了Cat.sks檔案Scene以下的內容。所以,如果要在Cat.sks掛載自定義類,應該掛載到Scene下面的節點。
實踐演示
有2個場景檔案,其元素結構為:
# Cat.sks 檔案
Scene (name = cat_scene)
-SKSPriteNode (Custom Class = CatNode)
# Main.sks檔案
Scene (Custom Class = MainScene)
-SKEditorReferenceNode (name = myRef,引用了Cat.sks)
在主場景中找到並使用CatNode類
// CatNode.swift class CatModelNode: SKNode { func hello() { print("hello") } } // MainScene.swift class MyShopScene: SKScene { override func didMove(to view: SKView) { super.didMove(to: view) let cat = childNodeDeep(withName:"myRef")?.getComponent(CatNode.self) cat?.hello() } }
SKNode擴充套件函式
為了找到自定義子節點,我為SKNode定義了幾個擴充套件函式:
extension SKNode {
//MARK: - 查詢子節點
/// 深入的遍歷所有節點,包括所有巢狀子節點
func enumerateChildNodesDeep(_ block: @escaping (SKNode) -> Void) {
var allNode = children
while allNode.count > 0 {
let n = allNode.removeLast()
block(n)
allNode.append(contentsOf: n.children)
}
}
func enumerateChildNodesDeep(withName name: String, using block: @escaping (SKNode) -> Void) {
enumerateChildNodesDeep { node in
if node.name == name {
block(node)
}
}
}
func childNodeDeep(withName name: String) -> SKNode? {
var result: SKNode?
enumerateChildNodesDeep(withName: name) { n in
result = n
return;
}
return result
}
func allNodeRunDefaultAction() {
enumerateChildNodesDeep { n in
n.isPaused = false
}
}
/// 獲取指定型別的節點
func getComponent<T>(_ type: T.Type) -> T? where T : SKNode {
if let me = self as? T {
return me
}
var result: T?
enumerateChildNodesDeep { n in
if let nT = n as? T {
result = nT
}
}
return result
}
}
其中的getComponent()函式,是借鑑了Unity獲取元件的方式。