gpt4 book ai didi

ios - SpriteKit : performance hit while preloading SKTextureAtlas

转载 作者:可可西里 更新时间:2023-11-01 03:12:42 25 4
gpt4 key购买 nike

我在预加载 SKTextureAtlas 时遇到了性能问题:

let textureAtlas = SKTextureAtlas(named: atlasName)
textureAtlas.preload(completionHandler: {
...
})

我所说的性能下降是指 FPS 在短时间内下降到大约 50。

我在 Instruments 中使用 Time Profiler 对其进行了测试,并验证了这项工作确实是在工作线程上完成的,如 documentation 中所述.

下图显示了 Time Profiler 捕获的尖峰,这是由预加载图集引起的。如您所见,大部分峰值是由 2 个工作线程引起的,据我所知,它们似乎都在加载图像数据。但是,恕我直言,这不会对主线程造成性能影响。

enter image description here

注意 1:我预加载的 .spriteatlas 不是那么大:4 个 Assets ,大约。 1000x1000 大小。

注意 2:我正在使用 iPhone 6、iOS 10、Xcode 8 进行测试。

注3:没有其他同时进行的实质性工作; CPU 一直徘徊在 30% 左右。 GPU 也是如此。

注意 4:在需要来自该图集的任何纹理之前请求图集预加载,因此它应该有足够的时间来预加载。

非常感谢任何帮助/指导!


更新

完成预加载的代码块:

let updateGroup = DispatchGroup()

for assetDefinition in assetContainmentDefinitions {

let assetName = assetDefinition.assetName

// Check if asset is not needed anymore and clear the cache with it
if progress >= assetDefinition.range.to {
if cachedAssets[assetName] != nil {
cachedAssets[assetName] = nil
}
}
// Check if asset is needed and if it's not already loading then preload and cache it
else if progress >= assetDefinition.range.from {

if currentlyLoadingAssets.contains(assetName) == false &&
cachedAssets[assetName] == nil {

currentlyLoadingAssets.append(assetName)

// Enter dispatch group
updateGroup.enter()

switch assetDefinition.assetType {
case .textureAtlas:

let textureAtlas = SKTextureAtlas(named: assetName)
textureAtlas.preload(completionHandler: {

DispatchQueue.main.async { [weak self] in

self?.cachedAssets[assetName] = textureAtlas
self?.currentlyLoadingAssets.remove(object: assetName)

// Leave dispatch group after preload is done
updateGroup.leave()
}
})

case .texture:

let texture = SKTexture(imageNamed: assetName)
texture.preload(completionHandler: {

DispatchQueue.main.async { [weak self] in

self?.cachedAssets[assetName] = texture
self?.currentlyLoadingAssets.remove(object: assetName)

// Leave dispatch group after preload is done
updateGroup.leave()
}
})
}
}
}
}

// Call completion after the dispatch group is fully completed
if let completion = completion {
updateGroup.notify(queue: DispatchQueue.main, execute: completion)
}

更新 2

我创建了一个空项目,其中只有 atlas preload block 。性能下降仍然发生。我尝试过使用多个 map 集,即使是只有一个 Assets 的 map 集

我也在这个空的新项目中尝试了@Sez 的建议(见下文),但在那种情况下甚至没有调用完成 block ,这似乎是 SKTextureAtlas 中的另一个错误> 类。 (?!)

let atlas = SKTextureAtlas(dictionary: ["texture1": UIImage(named: "texture1")!])

atlas.preload(completionHandler: { [weak self] in
print("COMPLETION BLOCK NOT CALLED")
self?.cachedAtlas = atlas
})

更新 3

我尝试删除 .spriteatlas 并创建具有相同纹理的 .atlas 并且(几乎)没有性能影响。但是,.atlas 不支持切片,这就是我首先要使用 .spriteatlas 的原因。

最佳答案

issues plaguing SKTextureAtlas (Apple Dev 论坛帖子)。

尝试使用 SKTextureAtlas:withDictionary: 提供 [String:UIImage] 字典创建纹理图集,method described on another StackOverflow post看看是否有帮助。

更新:如果你想要那个preload of the SKTexture发生在后台线程中,我会专门编写它而不是依赖于 preload 便利函数。

let atlas: SKTextureAtlas
let myImages: [String: UIImage] = getImages()
let globalQueue = DispatchQueue.global()
globalQueue.async {
let atlas = SKTextureAtlas(withDictionary:myImages)
for (k,v) in myImages {
let tex = atlas.textureNamed(k)
print(tex.size()) // force load
}
DispatchQueue.main.async {
completionHandler(atlas)
}
}

关于 app slicing ,只要您将 Assets 放在 Assets 目录中,它们就应该被切片。将构建上传到 iTunesConnect 后,您可以看到反射(reflect)这一情况的 App Store 大小报告。

iTunesConnect app store sizes

我有一段录制的直播视频,其中展示了这个导入过程。抱歉,它有点长(超过 2 小时),但这里的链接直接指向导入 Sprite 表的那一刻。

https://youtu.be/Ic9Wnux8vd8?t=1h17m

按照我在这里展示的方式进行操作,您会得到一个带有切片图像的 Sprite 图集。我的脚本(我在剪辑的前面演示过)是 on my GitHub如果你想要的话。

关于ios - SpriteKit : performance hit while preloading SKTextureAtlas,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40834615/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com