从另一个bundle加载spritekit场景?

时间:2018-06-06 20:37:23

标签: swift macos sprite-kit

我正在使用swift 4.2创建一个SpriteKit框架,并希望为场景和动作包含一些.sks文件。我尝试使用以下代码从捆绑中加载场景:

class func newGameScene() -> GameScene {

guard let gameScenePath = Bundle(for: self).path(forResource: "GameScene", ofType: "sks") else { assert(false) }

guard let gameSceneData = FileManager.default.contents(atPath: gameScenePath) else { assert(false) }

let gameSceneCoder = NSKeyedUnarchiver(forReadingWith: gameSceneData)

guard let scene = GameScene(coder: gameSceneCoder) else { assert(false) }


// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill

return scene

}

我加载场景并呈现它。 (此代码主要来自Apple的SpriteKit模板,因为我正在测试此问题。)

guard let view = view else {
      return nil
    }

    let scene = GameScene.newGameScene()

    view.presentScene(scene)

    view.ignoresSiblingOrder = true
    view.showsFPS = true
    view.showsNodeCount = true
    return nil

在这种情况下,GameScene.sks和代码在Apples模板中保持不变。此代码和.sks资产位于动态框架中,并导入到另一个项目中。

当框架将场景加载到我传递的视图中时,它会显示fps和节点数,但不显示“Hello,World!”文本。

在下面的代码中,也是从模板中复制的,一个断点显示当鼠标移动时不会调用它们。

    #if os(OSX)
// Mouse-based event handling
extension GameScene {

  override func mouseDown(with event: NSEvent) {
    if let label = self.label {
      label.run(SKAction.init(named: "Pulse")!, withKey: "fadeInOut")
    }
    self.makeSpinny(at: event.location(in: self), color: SKColor.green)
  }

  override func mouseDragged(with event: NSEvent) {
    self.makeSpinny(at: event.location(in: self), color: SKColor.blue)
  }

  override func mouseUp(with event: NSEvent) {
    self.makeSpinny(at: event.location(in: self), color: SKColor.red)
  }

}
#endif

我知道它必须与SpritKit如何加载场景但无法找到解决方案有关。我必须使用NSKeyedUnarchiver,因为SpritKit的内置文件初始化程序:

GameScene(fileNamed: "GameScene")

仅从主捆绑中加载。

现在在上面我假设可以使用编码器加载文件但是Tomato指出sks很可能不是使用编码器保存的。在这种情况下,可能无法使用Apple提供的api从sprite-kit中的另一个bundle加载sks文件。答案可能不包括编码员。

2 个答案:

答案 0 :(得分:1)

就像我认为let gameSceneCoder = NSKeyedUnarchiver(forReadingWith: gameSceneData)没有为你创造一个合适的编码器一样。

只做

guard let scene = NSKeyedUnarchiver.unarchiveObject(with: gameSceneData) as? SKScene
        else{
            assert(false)
    }

这将为您正确取消归档文件。

注意,如果您想使用GameScene,请确保在SKS文件的自定义类中设置GameScene

答案 1 :(得分:1)

我已经将以上讨论/解决方案编译为SKScene上的单个扩展功能。希望这对某人有帮助!

import SpriteKit

extension SKScene {
    static func fromBundle(fileName: String, bundle: Bundle?) -> SKScene? {
        guard let bundle = bundle else { return nil }
        guard let path = bundle.path(forResource: fileName, ofType: "sks") else { return nil }
        if let data = FileManager.default.contents(atPath: path) {
            return NSKeyedUnarchiver.unarchiveObject(with: data) as? SKScene
        }
        return nil
    }
}