将自定义 GKComponent 添加到 Xcode SpriteKit 场景编辑器中的实体会将 GKScene.rootNode 设置为 nil

hds*_*evi 7 xcode sprite-kit swift gameplay-kit ios13

当我CustomComponent (GKComponent)在 Xcode SpriteKit 场景编辑器中向实体添加 a并尝试.sks使用 a加载该文件时GKScene.initGKScene.rootNode未设置。更奇怪的是,这仅发生在 iOS 13 上,而不发生在 iOS 12 上。

我有一个小精灵套件 github 项目设置,它清楚地演示了这个问题。只需在 iOS 13 模拟器上运行该应用程序即可重现该问题。https://github.com/hdsenevi/answers-gkscene-rootnode-nil-bug

如果我CustomComponent从 SpriteKit 场景编辑器实体/精灵中删除,那么它运行良好。即:加载SKSceneGKScene.rootNode

  1. 从 Xcode SpriteKit 场景编辑器添加 GKComponents 时是否需要进行其他特殊修改?
  2. 我在这里遗漏了一些明显的东西吗?
  3. 为什么这段代码可以在 iOS 12 而不是 iOS 13 上正常工作?
  4. 在 iOS 13 中 SpriteKit 的功能是否与此有关?

以供参考

import UIKit
import SpriteKit
import GameplayKit

class GameViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Load 'GameScene.sks' as a GKScene. This provides gameplay related content
        // including entities and graphs.
        if let scene = GKScene(fileNamed: "GameScene") {

            // Get the SKScene from the loaded GKScene
            if let sceneNode = scene.rootNode as! GameScene? {

                // Copy gameplay related content over to the scene
                sceneNode.entities = scene.entities
                sceneNode.graphs = scene.graphs

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

                // Present the scene
                if let view = self.view as! SKView? {
                    view.presentScene(sceneNode)

                    view.ignoresSiblingOrder = true

                    view.showsFPS = true
                    view.showsNodeCount = true
                }
            } else {
                print("Error. No GameScene was found on GKScene.rootNode")
            }
        } else {
            print("Error loading GKScene file GameScene")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
import SpriteKit
import GameplayKit

class CustomComponent: GKComponent {
    override init() {
        super.init()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func didAddToEntity() {
        guard let gkSkNodeComponent = self.entity?.component(ofType: GKSKNodeComponent.self) else {
            print("Error. Cannot obtain a reference to GKSKNodeComponent")
            return
        }

        if let sprite = gkSkNodeComponent.node as? SKSpriteNode {
            sprite.texture?.filteringMode = .nearest
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

更新

关于我的设置的一些细节

  • macOS 莫哈韦沙漠 10.14.6
  • Xcode 11.0(在 10.1 和 10.3 上试过,行为相同)

小智 5

为了解决这个问题,你的组件需要重写变量supportsSecureCoding并且它必须返回 true。

这对我有用:

override class var supportsSecureCoding: Bool {
    return true
}
Run Code Online (Sandbox Code Playgroud)


小智 3

我也刚刚遇到了这个问题,并发送了一条反馈,其中包含本文的链接,因为它对问题进行了很好的描述。