プリロード時にパフォーマンス ヒットが発生していますSKTextureAtlas
。
let textureAtlas = SKTextureAtlas(named: atlasName)
textureAtlas.preload(completionHandler: {
...
})
パフォーマンス ヒットとは、FPS が短時間で 50 まで低下することを意味します。
でテストしTime Profiler
、ドキュメントInstruments
に記載されているように、この作業が実際にワーカー スレッドで行われていることを確認しました。
以下の画像は、Time Profiler
アトラスのプリロードによって引き起こされたスパイクのキャプチャを示しています。ご覧のとおり、スパイクのほとんどは 2 つのワーカー スレッドによって引き起こされており、私が理解できる限り、これらはすべて画像データを読み込んでいるようです。ただし、これによりメインスレッドの IMHO でパフォーマンスが低下することはありません。
注 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
アトラスプリロードブロックだけで空のプロジェクトを作成しました。パフォーマンスの低下は引き続き発生します。アセットが 1 つしかないアトラスでも、複数のアトラスを試してみました。
この空の新しいプロジェクトで@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