(这适用于 XCode 6 和 iOS 8 beta 4)
喜欢新的 SceneKit 编辑器。我已成功将 .sks 文件中的场景加载到自定义 SKScene 类中。但是,其中的对象被实例化为默认类(SKNode、SKSpriteNode 等),我不确定如何将它们绑定为实例化为自定义子类。
目前,我通过创建自定义类并将精灵节点作为属性链接来解决这个问题,而且效果很好
(这适用于 XCode 6 和 iOS 8 beta 4)
喜欢新的 SceneKit 编辑器。我已成功将 .sks 文件中的场景加载到自定义 SKScene 类中。但是,其中的对象被实例化为默认类(SKNode、SKSpriteNode 等),我不确定如何将它们绑定为实例化为自定义子类。
目前,我通过创建自定义类并将精灵节点作为属性链接来解决这个问题,而且效果很好
目前,您应该在添加到 SpriteKit 游戏模板的方法中按名称执行此操作。他们在 WWDC 2014 的 SpriteKit 最佳实践视频中介绍了这个主题。很容易错过,因为视频中有很多内容。
这是方法。
+ (instancetype)unarchiveFromFile:(NSString *)file {
/* Retrieve scene file path from the application bundle */
NSString *nodePath = [[NSBundle mainBundle] pathForResource:file ofType:@"sks"];
/* Unarchive the file to an SKScene object */
NSData *data = [NSData dataWithContentsOfFile:nodePath
options:NSDataReadingMappedIfSafe
error:nil];
NSKeyedUnarchiver *arch = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
[arch setClass:self forClassName:@"SKScene"];
SKScene *scene = [arch decodeObjectForKey:NSKeyedArchiveRootObjectKey];
[arch finishDecoding];
return scene;
}
它是一个类别SKScene
,包括一个方法,用于NSKeyedUnarchiver
在从 mainBundle 中的 .sks 文件加载时替换该类。在 iOS 中,他们将其添加到GameViewController.m
文件中,而在 OS X 中,他们将其添加到AppDelegate.m
文件中。
在此处或您的各个 SKNode 子类中,您可以实现它。这就是他在下面的帖子中所做的。这是由 Apple 提供的,并在 WWDC 视频中进行了介绍。我想明年它会得到更好的处理。在此期间,请求 SKNodes 的错误文件会获得类似 IBDesignable for Scene Editor 的内容。:)
我写了一个小助手来处理这个问题:https ://github.com/ice3-software/node-archive-delegate 。它使用NSKeyedUnarchiverDelegate
来按名称对您的精灵进行子类化。
我做了一个小技巧如何使用 SceneKit 编辑器,我会尝试使用它,但我不确定这会如何降低性能。我想使用场景编辑器制作复杂的 SKNodes 结构并将它们加载到当前场景中。它还可以帮助子类化节点。
我在场景编辑器中配置我的节点,将父节点设置为名为“base”的空节点,并创建了 SKNode 的子类。然后我创建了一个 init 方法,并在需要时在我的场景中调用它:
// subclass code
class MyOwnSKNodeSubclass: SKNode {
let nodeLayer = SKNode()
init(fromNode: SKNode){
super.init()
nodeLayer.addChild(fromNode.childNodeWithName("base").copy() as SKNode)
addChild(nodeLayer)
}
}
// scene code
if let myNode = SKNode.unarchiveNodeFromFile("MyScene")
{
// you can use your subclass here
let node = MyOwnSKNodeSubclass(fromNode: myNode)
addChild(node)
}
我还使用了自己的 SKNode 扩展,差别不大,但是:
class func unarchiveNodeFromFile(file:String) -> SKNode?{
if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
var nodeData = NSData.dataWithContentsOfFile(path, options: .DataReadingMappedIfSafe, error: nil)
var archiver = NSKeyedUnarchiver(forReadingWithData: nodeData)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKNode")
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as SKNode
archiver.finishDecoding()
return scene
} else {
return nil
}
}
正如我所说,我不确定生产力,但我认为如果不经常使用它不会造成太大伤害。希望这可以帮助某人。
是的,Apple 应该让我们所有人都更容易做到这一点,但就目前而言,这是满足我需求的最可行的解决方案:
避免子类化
当然,这可能根本不可能,但就我而言,我想到的子类包含控制我在 SKS 文件中布局的图形的逻辑......听起来非常接近 ViewController,不是吗?
我创建了一个OverlayController
类,并使用以下命令对其进行初始化:
self.childNodeWithName(Outlet.OverlayNode)!
所以现在,overlay 节点只是一个哑节点,而控制器是具有所有优点的完整子类。
但还有更多
只是为了让交易更甜蜜:
private extension SKNode {
var progressBar: SKNode {
return self.childNodeWithName("ProgressBar")!
}
}
这是新控制器类文件中的私有扩展,因此我们可以轻松访问哑元的子级SKNode
。
痛点
一个公认的痛点是触摸处理。将 SKNode 子类化以进行自定义触摸处理是很自然的,而组合方法在这方面几乎没有任何作用。我现在正在转发现场的触摸,但如果有更好的方法,我会发布更新。