LZMAおよびLZ4圧縮に関する疑問の分析

今回の主な話題は:LZMAおよびLZ4圧縮に関する疑問の分析、パーティクルシステムがGPUインスタンス化をサポートできるかどうか、スクリプトのコンパイルWarningを一時的にブロックする方法はありますか?


AssetBundle

Q1: 昨日、Q&AコミュニティでLZMAとLZ4圧縮に対するUWA_Xinの回答を見ましたが、ここでいくつか質問があります。

質問1:インターネットである記事を見て、AssetBundleがロード時に解凍するためにメモリの一部を拡張する必要があると述べました。「解凍」という言い方には問題があると思います。すべてが解凍されている場合、アセットはすでにメモリ内にあるため、LoadAsset必要はありません。また、テストしたところ、LZ4はLZMAより200MBメモリ小さくなるため、LZ4のAssetBundleのサイズを追加することだけではなく、AssetBundleをロードするときにLZMAがすべてのアセットを解凍すると思っています。

LZMA圧縮を使用する場合、LoadFromCacheは最初の読み取り時に非常に時間がかかります。なぜなら、CacheはAssetBundleパッケージをLZ4に再圧縮し、2回目の読み取りを高速化させますから。したがって、上のスクリーンショットに記載されているLZMAはAssetBundleをLZ4に再圧縮することは、実にはLoadFromFileではなく、LoadFromCacheインターフェイスに対することです。LoadFromFileはハードディスクから直接読み取られると思います。Cache操作がないため、上の図は言い違いですか?

 

質問2:LZ4圧縮AssetBundleパッケージはChunkに従って読み取られるため、AssetBundleパッケージを解凍すると、通常、AssetBundleのヘッダーファイル情報が読み取られます。したがって、AssetBundleパッケージを解凍する時、LZ4のChunk利点に利点はありませんか?AssetBundleをロードするとき、LZMAとLZ4の速度は同じはずですか?(LZMAがパッケージ全体を完全に解凍する場合は、別の話になります)。

回答1:「「解凍」という言い方には問題があると思います。すべてが解凍されている場合、アセットはすでにメモリ内にあるため、LoadAsset必要はありません。」

「解凍」と「ロード」は別の話です。問題主が言った記事にある「解凍」はWWWインターフェイス用です。WWWはLZMAをロードし、メモリに解凍する必要がありますが、これは、圧縮されていないAssetBundleと同等のバイナリストリームと見なすことができ、後続のLoadAssetはまだ必要です。ただし、2回目にLoadFromCacheをコールするからは不要です。これは、ディスクのCacheにはすでに「圧縮されていないAssetBundle」で存在していますから。

上記のLZMAはAssetBundleをLZ4に圧縮します。これはLoadFromCacheの場合だけでなく、LoadFromFileも同じですが、LoadFromFileはディスクにCacheされず、完全にメモリで実行されるため、このインターフェイスはLZMAのAssetBundleをロードするときに同じように遅く変更され、メモリも大幅に増加する。

 

回答2:質問1の説明によると、LZMAと比較してAssetBundleをロードする場合、LZ4には依然として大きな利点があります。しかし、まだ疑問が一つ残ってあります。私たちがテストをした時に使用したのはLZ4で、LZMAと比べるとメモリは200MBぐらい小さいです。だからLZMAはABをロードする時にアセットを全て解凍し、ただ一つLZ4のAssetBundleサイズを追加することではありません。ここでいくつかのテストを行った後、メモリの違いは、LZ4のサイズではなく、実際には非圧縮のAssetBundleのサイズに近くなっています。

では、問題主にもう1ステップを実行することをお勧めします。それは、使用するAssetBundleを非圧縮にして、200MBに近いかどうかを確認することです。


パーティクルシステム

Q2:パーティクルシステムはGPU Instancingをサポートできますか?いくつかの例を実行しましたが、GPU Instancingが有効になれるかどうかを確認できませんでした。

Unity 2018はすでにパーティクルシステムのGPU Instancingをサポートしていますが、Meshモードである必要があります。詳細については、このドキュメントを参照してください。


ロード

Q3:コードでTextureを宣言してイメージをロードすれば、このComponentを廃棄しても、このGameObejctを廃棄しても、Textureのメモリは解放されませんか?OnDestroyで破棄する必要がありますか?

テクスチャのメモリは1つだけですが、複数のオブジェクトによって引用される可能性があるため、ComponentまたはGameObjectの破棄を追跡することはできません。

アセット管理(特定のテクスチャは現在のフレームに使用されず、2フレーム後に再び使用される可能性があり、この部分のIO消費は小さくないため、開発者自身で管理する必要があります)を考慮したかもしれないために、この部分はGCではなりません。Resources.UnloadAssetを使用して、Textureをアンロードします。

 

Componentの破棄またはGameobjectの破棄では、new されたTextureのメモリは削除されません。Object.Destroy()メソッドをコールして、new されたTextureオブジェクトをパラメータとして入力し、Profilerをチェックして検証できます。


エディター

Q4:スクリプトのコンパイルWarningを一時的にブロックする方法はありますか?例えば、「The variable 'xxx' is declared but never used」みたいもの。

File->Build Settings->Player Settings->Logging

 

問題主にこれらのWarningをブロックするのではなく修正することを強くお勧めします。プログラムとしては、「Bugのない」はデッドライン、「Warningのない」は合格線でありと思っています。特に例を挙げたものです。エディターはそれを最適化するのに役立ちますが、他のロジックを書く時に裏切りものになる可能性は非常に高いです。


アニメーション

Q5:ゲームが一定期間実行された後、一つのCPU に高く占用する関数Director.ProcessPlaySateChangesが表示されます。これには3616msかかります。どのように発生しましたか?C#コードにそのようなメソッドコールはないことはもう確認しました。(Unity バージョンは5.6.5p3)

もう分かりました。UIにある一つのアニメーションは再生する前に関数Animator.Rebind()を使用しましたから。


UWA公式サイト:https://jp.uwa4d.com

UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意):https://answer.uwa4d.com