我在预加载时遇到了性能问题SKTextureAtlas
:
let textureAtlas = SKTextureAtlas(named: atlasName)
textureAtlas.preload(completionHandler: {
...
})
通过性能打击,我的意思是 FPS 在短时间内下降到约 50。
我用Time Profiler
in对其进行了测试,Instruments
并验证了这项工作确实是在工作线程上完成的,如文档中所述。
下图显示了Time Profiler
由预加载图集引起的尖峰捕获。如您所见,据我所知,大部分峰值是由 2 个工作线程引起的,它们似乎都在加载图像数据。但是,这不应该对主线程恕我直言造成性能影响。
注 1:.spriteatlas
我预加载的不是那么大:4 个资产,大约。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 预加载块。性能下降仍然存在。我已经尝试过多个地图集,即使只有一个资产的地图集。
在这个空的新项目中,我也尝试了@Sez 的建议(见下文),但在这种情况下,甚至没有调用完成块,这似乎是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
的原因。