watchOS - SpriteKit 应用程序因 CPU 使用率过高而终止

watchOS - SpriteKit app getting killed because of too much CPU Usage

提问人:Georg 提问时间:11/3/2023 更新时间:11/3/2023 访问量:19

问:

我的问题发生在 watchOS 上,但我想这是一个一般的 SpriteKit 问题 所以。。。我有一个 watchOS 应用程序,它正在渲染 SpriteKit 场景(基本上是自定义 MapView)。当我的用户在手表上平移时,我会更新我的 SpriteKit 的位置,当用户转动表冠时,我会更新它的比例。

因此,现在当用户非常疯狂地疯狂地平移和缩放时,我的场景将不得不经常更新,这将导致“崩溃”,原因是我超出了 CPU 限制。

e.g.:
CPU: 9 seconds cpu time over 20 seconds (46% cpu average), exceeding limit of 15% cpu over 60 seconds

当 sprit-nodes 离开屏幕时,我已经缓存了它们(并在我可能再次需要它们时重用它们,而不仅仅是删除它们),这让事情变得更好,但是如果没有重用 sprite,CPU 使用率仍然会再次上升。 大部分时间都花在这里:

let texture = SKTexture(image: image)
let node = SKSpriteNode(texture: texture)

你会如何处理?一段时间后限制用户输入?或者是否有任何我尚未发现的 Info.plist 检查告诉 watchOS 如果我的应用程序使用更多一点就可以了?

iOS SwiftUI Sprite-Kit watchOS

评论

0赞 lorem ipsum 11/3/2023
也许试着“去抖动”一点
0赞 Georg 11/6/2023
我现在做到了,是的......我将更新调用限制在 10fps 左右......这对于我的用例来说已经足够了。我也不确定是否是 SwiftUI 包装器可能会导致问题。将不得不再调试一下......谢谢你的帮助!

答:

0赞 Luca Angeletti 12/11/2023 #1

本说明

let texture = SKTexture(image: image)

很贵,因为正如 Apple 文档所述:

在将控制权返回到游戏之前,将复制图像数据。

纹理贴图

相反,您应该利用这种方式TextureAtlas

guard
    let enemyImage = UIImage(named: "panda.png"),
    let heroImage = UIImage(named: "hero.png")
else {
    fatalError()
}
let textureAtlas = SKTextureAtlas(dictionary: ["enemy": pandaImage,
                                               "hero": heroImage])

接下来,当你需要使用你编写的特定纹理来实例化一个精灵时

guard let heroTexture = textureAtlas.textureNamed("hero") else { fatalError() }
let hero = SKSpriteNode(texture: heroTexture)

静态生成 TextureAtlas

您也可以按照以下说明让 Xcode 为您填充 TextureAtlas。

雪碧图集

或者,您可以按照这些说明切换到更现代的 SpriteAtlas 技术。

笔记

当然,用更合适的错误管理来代替。fatalError()

评论

0赞 Georg 12/12/2023
非常感谢您的回复!问题是我的 SpriteKit 应用程序不是一个游戏,而是一个地图视图(苹果现在确实允许在 watchOS 上自定义磁贴),我在其中动态加载每个精灵的内容。我已经实现了更多的缓存,这减少了相当多的时间。但是,当然,任何包含该附加信息的进一步提示都将非常受欢迎!!再次感谢您的详细回答!