当前位置:  开发笔记 > 运维 > 正文

麻烦继承SCNScene

如何解决《麻烦继承SCNScene》经验,为你挑选了1个好方法。

我一直在尝试将SCNScene子类化,因为这似乎是保持场景相关逻辑的最佳位置.现在我不确定是否已经推荐了所以我的第一个问题是 - 我是否应该继承SCNScene,如果不是为什么不呢?文档似乎表明它很常见,但我在线阅读的评论表明我不应该将其子类化.废话,我正在查看文档SKScene.在SCNScene类引用只字不提子类.

假设以这种方式构建我的游戏是可以的,这是我的进步

//  GameScene.swift

import Foundation
import SceneKit


class GameScene: SCNScene {

    lazy var enityManager: BREntityManager = {
        return BREntityManager(scene: self)
    }()

    override init() {
        print("GameScene init")
        super.init()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }


    func someMethod() {
        // Here's where I plan to setup the GameplayKit stuff
        // for the scene
        print("someMethod called")
    }

}

注意:我正在lazy var按照这个问题的答案使用

在我的视图控制器中,我试图像这样使用GameScene

class GameViewController: UIViewController {

    override func viewDidLoad() {

        super.viewDidLoad()

        // create a new scene
        let scene = GameScene(named: "art.scnassets/game.scn")!

        // retrieve the SCNView
        let scnView = self.view as! SCNView

        // set the scene to the view
        scnView.scene = scene

        // Should print "someMethod called"
        scene.someMethod()
    }
}

但是,调用会GameScene.someMethod()触发EXEC_BAD_ACCESS错误.

此外,如果我省略了调用GameScene.someMethod,则场景正确加载,但是被覆盖的初始化器GameScene似乎没有被调用.

我不确定这里发生了什么.很明显,在Swift中有一些关于子类化的东西我还没有理解.或者也许是某些方面的事情意味着我错过了.



1> rickster..:

我应该是子类SCNScene,如果不是,为什么不呢?

不,你不需要子类,你可能最好不要继承子类.SCNScene更像基本数据/模型类(NSString,UIImage等)大于样行为/控制器/视图类(UIViewController,UIControl等).也就是说,它是某种东西的一般描述或容器(在这种情况下,是3D场景),并不真正提供行为.由于行为方式不多,因此没有太多机会用子类覆盖行为.(也不是围绕子类入口点设计的类意图被覆盖,比如viewDidLoad和诸如此类的东西.)

虽然可以进行子类化SCNScene,但这样做并没有获得太多收益,而且某些API可能无法按预期工作......

但是,调用会GameScene.someMethod()触发EXEC_BAD_ACCESS错误.

此外,如果我省略了调用GameScene.someMethod,则场景正确加载,但是被覆盖的初始化器GameScene似乎没有被调用.

一个.scn文件实际上是一个NSKeyedArchiver存档,这意味着它里面的物品有被用来创建相同的类.当你调用init(named:)你的SCNScene子类,父类的实现,最终调用,直至NSKeyedUnarchiver unarchiveObjectWithData:加载存档.如果没有一些unarchiver修改,那么该方法将实例化一个SCNScene,而不是你的子类的实例.

因为您没有获得子类的实例,所以不调用子类初始值设定项,并且尝试调用子类的方法会导致运行时错误.

旁白:为什么SpriteKit与SceneKit不同?SKScene有点奇怪的是,它既不是纯粹的模型类,也不是纯粹的控制器类.这就是为什么你会看到很多项目,包括使用SKScene子类的Xcode模板.然而,这种方法有一些缺点 - 如果你不仔细计划,你的游戏逻辑很容易与你的游戏数据紧密结合,这使得扩展你的游戏(比如说,到多个级别)需要繁琐的编码而不是数据编辑.有一个关于这个主题的WWDC 2014会议非常值得关注.

那么该怎么办?

你有几个选择......

    不要子类.将您的游戏逻辑保持在一个单独的类中.这不一定是视图控制器类 - 您可以拥有Game视图控制器或应用程序委托所拥有的一个或多个对象.(如果您的游戏逻辑在多个场景的内容之间转换或操纵多个场景的内容,这尤其有意义.)

    子类,但安排将未归档的东西SCNScene放入子类的实例中 - 实例化您的子类,加载一个SCNScene,然后将其根节点的所有子节点移动到子类的根节点中.

    子类,但强制NSKeyedUnarchiver加载您的子类而不是SCNScene.(您可以使用类名映射执行此操作.)

其中,#1可能是最好的.

推荐阅读
mobiledu2402851173
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有