以前,我在质疑是否可以使用Scene编辑器创建复杂的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文件隔离开并添加时没有运气
最佳答案
问题不在于是否将其加载为未存档的文件还是将其加载为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)
}