(这是适用于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
类别中的一个方法,用于在从mainBundle加载的.sks文件中使用NSKeyedUnarchiver
替换类。在iOS中,将其添加到GameViewController.m
文件中,在OS X中将其添加到AppDelegate.m
文件中。
您可以在此处或您自己的SKNode子类中实现此功能。这就是下面文章作者所做的。此功能由Apple提供,并在WWDC视频中进行了介绍。我想明年会有更好的处理方式。与此同时,提交一个bug请求,以便为Scene Editor获取类似于IBDesignable的东西。 :)
-setupLevel1
方法只能从.sks文件中提取可以插入其中的节点(而不能是用户定义的子类)。 - Ephemera[arch setClass:MySpriteNodeSubclass forClassName:@"SKSpriteNode"]
吗? - EphemeraNSKeyedUnarchiverDelegate
通过名称对你的精灵进行子类化。我有一个小技巧,可以使用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
}
}
正如我所说,我不确定生产力会受到多大影响,但我认为如果不经常使用这个功能,它不会对生产力造成太大的伤害。希望这能对某些人有所帮助。
self.childNodeWithName(Outlet.OverlayNode)!
现在,覆盖节点只是一个简单的节点,控制器是具有所有好处的全功能子类。
但还有更多
这只是为了让事情更美好:
private extension SKNode {
var progressBar: SKNode {
return self.childNodeWithName("ProgressBar")!
}
}
这是新控制器类文件中的一个私有扩展,因此我们可以轻松地访问愚蠢 SKNode
的子元素。
痛点
一个令人痛苦的问题是触摸处理。自定义触摸处理通常会通过对 SKNode 进行子类化来实现,而组合方式在这方面几乎没有任何作用。我现在正在从场景中转发触摸事件,但如果有更好的方法,我会发布更新。