解析
假設有一個 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獲取組件的方式。