【问题标题】:Loading SpriteKit scene on background thread causes app to crash because of memory issues在后台线程上加载 SpriteKit 场景会导致应用程序因内存问题而崩溃
【发布时间】:2018-11-25 22:08:06
【问题描述】:

我遇到了这个奇怪的问题。在我的游戏中,我从 .sks 文件加载场景。当我在主线程上加载它时,我没有任何问题。一切都很好。但是当我在后台线程上加载时,应用程序由于内存问题而崩溃。这是我的代码...

DispatchQueue.global(qos: .background).async {
    let nextScene = World(fileNamed: "GameScene")
        DispatchQueue.main.async {
            self.nextScene = nextScene
            self.playerRunningState = .RUNNINGRIGHT
        }
}

有谁知道为什么这会在主线程上工作,而不是在后台线程上工作。

仅供参考,它在以下行崩溃:

let nextScene = World(fileNamed: "GameScene")

【问题讨论】:

  • 请发布您的世界一流水平,因为这是您的问题所在。

标签: ios swift memory-management sprite-kit


【解决方案1】:

在 Apple 文档中引用的操作节点时,SpriteKit 不是线程安全的:https://developer.apple.com/documentation/spritekit/sknode

对节点的操作必须发生在主线程中。 SKViewDelegate、SKSceneDelegate 和 SKScene 的所有 SpriteKit 回调都发生在主线程中,这些是对节点进行操作的安全位置。但是,如果您在后台执行其他工作,则应采用类似于清单 1 的方法。

所有操作都必须在主线程上同步进行,创建一个新节点就是一种操作。如果你想在主线程之外对节点进行操作,那么你必须采用这种方法:

 class ViewController: UIViewController {
    let queue = DispatchQueue.global()

    var makeNodeModifications = false

    func backgroundComputation() {
        queue.async {
            // Perform background calculations but do not modify 
            // SpriteKit objects

            // Set a flag for later modification within the 
            // SKScene or SKSceneDelegate callback of your choosing

            self.makeNodeModifications = true
        }
    }
}
extension ViewController: SKSceneDelegate {
    func update(_ currentTime: TimeInterval, for scene: SKScene) {
        if makeNodeModifications {
            makeNodeModifications = false

            // Make node modifications
        }
    }
}

【讨论】:

  • 在后台线程中创建节点并不是在操作它。您可以在后台线程中创建您想要的所有节点,您只需要确保在将它们放入游戏中以由更新循环处理之前完成它们。他在后台线程中创建一个节点,然后在主线程中进行操作,这是允许的。如果我不得不猜测的话,World 的 init 中正在发生一些事情,正在对节点进行操作,这导致了他的问题。
  • 当你从一个文件初始化一个场景时,它被认为是一种操作,不受程序员控制,而是由 SpriteKit 系统控制
  • 谁说的?从文件加载只是取消归档并通过编码器初始化。
  • 我使用后台加载来准备我的场景白色播放器正在通过主菜单设置以避免加载时间,没有线程问题,因为引擎尚未处理场景。跨度>
  • 您在主线程上进行操作的原因是您不知道会发生什么以及调度程序何时切换线程。您可能正处于物理计算的中间,并且触发了一个后台线程,该线程删除了它试图计算的节点。繁荣你现在有不良行为。但是创建一个节点与创建一个对象的任何其他实例没有什么不同。这只是内存,还没有使用任何东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多