• SpriteKit 获取SKrefenceNode中的自定义类


    解析

    假设有一个 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获取组件的方式。

  • 相关阅读:
    JDK源码分析之hashmap就这么简单理解
    JVM笔记11-类加载器和OSGI
    JVM笔记10-性能优化之高级特性
    Java并发编程笔记之ThreadLocal内存泄漏探究
    Java并发编程笔记之FutureTask源码分析
    Java并发编程笔记之SimpleDateFormat源码分析
    Java并发编程笔记之Timer源码分析
    Java并发编程笔记之Semaphore信号量源码分析
    Java并发编程笔记之CyclicBarrier源码分析
    Java并发编程笔记之 CountDownLatch闭锁的源码分析
  • 原文地址:https://www.cnblogs.com/ZJT7098/p/16320775.html
Copyright © 2020-2023  润新知