Ответ 1
Я написал маленького помощника делегата, чтобы справиться с этим: https://github.com/ice3-software/node-archive-delegate. Он использует NSKeyedUnarchiverDelegate
для подкласса ваших спрайтов по имени.
(это для XCode 6 и iOS 8 beta 4)
Возлюбите новый редактор SceneKit. Я успешно загружаю сцену из файла .sks в собственный класс SKScene. Тем не менее, объекты внутри него создаются как классы по умолчанию (SKNode, SKSpriteNode и т.д.), И я не уверен, как их привязывать к экземпляру вместо пользовательских подклассов.
В настоящее время я обойдусь тем, что создавая пользовательские классы и привязывая к вершинам спрайтов как свойство, и это работает нормально
Я написал маленького помощника делегата, чтобы справиться с этим: https://github.com/ice3-software/node-archive-delegate. Он использует NSKeyedUnarchiverDelegate
для подкласса ваших спрайтов по имени.
В настоящее время вы должны делать это по имени в методе, добавленном в шаблоны игр SpriteKit. Они освещают эту тему в видеоролике SpriteKit Best Practices на WWDC 2014. Легко пропустить, потому что в нем много чего.
Вот этот метод.
+ (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
для замены класса при загрузке из файла .sks в mainBundle. В iOS они добавляются в файл GameViewController.m
, а в OS X они добавляются в файл AppDelegate.m
.
Здесь или в ваших индивидуальных подклассах SKNode вы можете реализовать это. Это то, что он сделал ниже в своем посте. Это было предоставлено Apple и охвачено видео WWDC. Думаю, в следующем году все будет лучше. Тем временем файл с ошибкой, запрашивающий SKNodes, получает что-то вроде IBDesignable для Scene Editor.:)
Я сделал небольшой трюк, как использовать редактор SceneKit, и я попытаюсь его использовать, но я не уверен, как это может снизить производительность. Я хочу использовать редактор сцен, чтобы создавать сложные структуры SKNodes и загружать их в текущую сцену. Он также может помочь с узлами подкласса.
Я настраиваю свой node в редакторе сцены, устанавливаю родительский node как пустой node, называемый "базой", и создавал подкласс 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)!
Итак, теперь наложение node является просто немым node, а контроллер - полноценным подклассом, который имеет все полезные свойства.
Но есть больше
Просто бросьте это, чтобы подсластить сделку:
private extension SKNode {
var progressBar: SKNode {
return self.childNodeWithName("ProgressBar")!
}
}
Это частное расширение внутри нового файла класса контроллера, поэтому мы можем безболезненно обращаться к дочерям немого SKNode
.
Точка боли
По общему признанию, болезненным моментом является сенсорная обработка. Естественно подклассифицировать SKNode для пользовательской обработки касания, и композиционный подход практически ничего не делает на этом фронте. На данный момент я перенаправляю штрихи со сцены, но буду отправлять обновления, если есть лучший способ.