以前我质疑是否可以使用场景编辑器创建复杂的SKSpriteNodes,而不是仅使用它来布局SKScenes。在@Anton Rogachevskyi the previous question的帮助下,我开始使用unarchiveNodeFromFile来定位.SKS文件。它按照我的预期加载sks文件,但是当我尝试将它添加到当前场景时,没有任何内容出现。如果我在addChild行中断并预览它在预览窗口中正确显示的对象,所以我知道它正在找到正确的文件。在sks文件中是一个自定义对话框类,并在"所需的init中设置断点?(编码器aDecoder:NSCoder)"我可以告诉自定义对象正在初始化。
在对话框类中我以编程方式向对象添加一个粉红色的框,以显示它确实到达了类的初始化
class TeamDialog: SKSpriteNode {
init(size: CGSize) {
super.init(texture: nil, color: .red, size: size)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup() {
let pinkBox = SKSpriteNode(color: .magenta, size: CGSize(width: 100, height: 100))
pinkBox.zPosition = 500
addChild(pinkBox)
}
}
在场景中,这是我找到对象并尝试将其添加到场景中的方式,它出现在预览中但屏幕上没有显示任何内容
private func displayDialog() {
if let wtf = unarchiveNodeFromFile(file: "TeamDialog")! as SKNode? {
let layer = SKSpriteNode(color: .clear, size: self.size)
layer.zPosition = 5000
layer.position = CGPoint(x: self.size.width / 2, y: self.size.height / 2)
addChild(layer)
for child in wtf.children {
print("child \(child.name)")
if let teamDialog = child as? TeamDialog {
teamDialog.removeFromParent()
layer.zPosition = 1
layer.addChild(teamDialog)
}
}
}
}
func unarchiveNodeFromFile(file: String) -> SKNode? {
if let path = Bundle.main.path(forResource: file, ofType: "sks") {
let fileData = NSData.init(contentsOfFile: path)
let archiver = NSKeyedUnarchiver.init(forReadingWith: fileData as Data!)
archiver.setClass(SKNode.classForKeyedUnarchiver(), forClassName: "SKScene")
let node = archiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) as! SKNode
archiver.finishDecoding()
return node
} else {
return nil
}
}
同样,我可以在预览窗口中看到它,但是当它被添加到场景中时没有任何内容。
在将其添加到场景之前,我是否必须处理已取消归档的对象或对其执行某些操作?
我将代码拉出来并将其放入具有相同结果的测试项目中。
我尝试将sks文件(作为节点)添加到场景中,没有运气,我尝试从sks文件中隔离出对话框并添加它没有运气
答案 0 :(得分:2)
问题不在于是否将其作为未归档文件加载,或者是否将其加载为SKReferenceNode。虽然在找到并研究这个SKReferenceNode之后,确实可以采用这种方式,并且可能是为了这个目的而做的。
问题在于,在场景编辑器中,自定义对象位于场景旁边(x = -1500),因为当我最初构建它时,它位于scene.sks文件中,我并不想要它在场景对象。当我将它转移到它自己的sks文件时,它保持了它的定位。我没想到这是一个大问题,因为在我将sks文件加载到变量中后,我在代码中将它设置为CGPoint(x:0,y:0)。问题是您无法在现有场景周围移动加载的场景对象,因此如果它在屏幕外,它将保持在屏幕外。设置位置没有任何作用,如果它是一个未归档的文件或它不会移动的SKReferenceNode也没关系。
所以我引用了sks文件中的第一个孩子并设置了它的位置和中提琴!
如果有人对此设置可以执行的操作感兴趣,您可以在自己的sks文件中创建和布局复杂的自定义对象,然后将它们加载到场景文件中。这样做的好处是你的sks文件不会变得杂乱,然后你的自定义对象sks可以在多个不同的场景中被引用。
let path = Bundle.main.path(forResource: "TeamDialog", ofType: "sks")
let dialogScene = SKReferenceNode (url: URL (fileURLWithPath: path!))
if let teamDialog = dialogScene.childNode(withName: "//teamDialog") as? TeamDialog {
teamDialog.setup(scene: self)
teamDialog.position = CGPoint(x: 0, y: 0)
dialogScene.zPosition = 5000
addChild(dialogScene)
}