UIにおいてSetActiveが大量に使用される問題
今回の話題:
1)UIにおいてSetActiveが大量に使用されるなら、どのように最適化するか
2)ASTC圧縮とETC2圧縮によって生成されたAPKパッケージの問題
3)PNG画像形式とTGA画像形式の問題
4)ゲーム実行のクラッシュの問題
5)AssetBundleの読み込み方法に適用できる環境
UI
Q:UIの日常開発では、特定のGOを表示または非表示にするために、多くのSetActive(true)/(false)コードが使用されます。しかし、SetActiveのコストが大きすぎるので、SetActiveを使用したくありません。他の解決策はありますか?
A1:この状況には、Active/Deactiveのコストには主にいくつかの側面があります。
1.C#層からNative層へのシャトルコール速度は、C#層よりも遅くなります。
2.UI要素を変更すると、所属Canvasが変更され、関数Canvas.SendWillRenderCanvases()およびCanvas.BuildBatch()がトリガーされ、高い時間コストを引き起こします。
3.UI要素のメッシュ頂点配列を変更すると、MONOメモリの割り当てが発生し、GCがトリガーされ、高い時間コストを引き起こします。(ただし、UI要素の位置を移動したらMONOメモリの割り当ては発生しません)。
したがって、最適化は次の点からも考慮することができます。
1.C#層で変数を設定して、対応するGOがActive状態かDeactive状態かをマークし、ActiveオブジェクトではSetActive(true)を回避し、非activeオブジェクトではSetActive(false)を回避します。ActiveでSetActive(true)を実行すると、「最下層」が判断を下しますが、コールした際、最下層はすでにC#層からコールされているため、コストが高くなります。 C#層で適切に判断することで、最下層に判断させることを回避できます。
2.頻繁に変更されるUI要素とまれに変更されるUI要素を別のCanvasに配置して、UI要素の変更による時間コストを減らします。
3.UI要素の座標をCanvasの範囲外に移動して表示および非表示にし、SetActiveの時間とSendWillRenderCanvasesの時間を回避します。
4.テスト後、Componentにenabled = falseの操作を行うことは、GOにSetActive(false)の操作を行うことより時間が少なくかかりません。
5.CanvasGroupコンポーネントを追加して透明度を設定することにより、表示と非表示を表します。
A2:最近最適化を行い、この問題も気づきました。特に、ImageとTMPTextがハングアップされている時にSetActive場合、時間コストがもっと長くなります。そして、次の側面から最適化しようと思います。
1.UICanvasをハングアップものに対し、Layer層を直接変更します。
2.UICanvasをハングアップしないものに対し、CanvasGroupをハングアップしてAlphaを制御するように変更します。ここにはやや面倒なところがあります。こちらのプロジェクトは長い間開発されたため、インターフェイスの方に、制御が必要なノードにCanvasGroupをハングアップさせることは現実的ではありません。実行時にコンポーネントを動的にハングアップことには、パフォーマンスに関するいくつかの懸念があります。そのため、実行時にActiveの変更が発生するノードに見たら、対応するPrefabにCanvasGroupコントロールを追加することで、PrefabがCanvasGroupコントロールをうまく補足するようになります。正式なリリース後、欠落がない場合は、SetActiveを直接使用してください。
3.CanvasGroup方法は欠点があります。つまり、Alphaだけが変更され、レイアウトは引き続き使用されるため、親インターフェイスはLayoutであり、CanvasGroupは使用できません。最初の計画は、SetScale0とSetActiveの時間コストを比較することです。どちらも、再描画を引き起こすはずです。
Texture
Q:空のプロジェクトで、2048 * 2048の大きな画像をいくつか入れました。ETC24bitsで圧縮した場合、1枚のシートのサイズは2MBで、ASTC6X6で圧縮した場合、1枚のシートのサイズは1.8MBです。
個人的な理解によると、ASTC圧縮形式で生成されたAPKは小さいはずですが、まさか予想と正反対とは思いませんでした。ETC2圧縮で作成されたAPKは21.1MB、ASTC圧縮で作成されたAPKは25.7MBです。
ETC2で圧縮されたパッケージが小さいのはなぜでしょう、ASTCによって作成されたAPKは大きいのはなぜでしょうか?
A:占有されているパッケージのサイズと、EditorのPreviewインターフェイスに表示されるサイズは異なるものです。
Previewインターフェイスに表示されるサイズは、ASTCまたはETC2のアセットのサイズであり、パッケージ化後、そのアセットはさらに圧縮されます(LZ4またはLZMA)。 LZ4に圧縮されたETC2が占めるパケットのサイズは、LZ4に圧縮されたASTCが占めるサイズよりも実際に小さいとしか説明できません。理由は、特定の圧縮アルゴリズムの実装によって異なります。
AssetBundleを使用して確認できます。AssetBundleパッケージ化時にNoCompressionが選択されている場合、確かにASTC形式はETC2形式のAssetBundleパッケージよりも小さくなります。 LZ4またはLZMA圧縮を選択した場合、ETC2形式のAssetBundleはASTC形式のAssetBundleよりも小さくなります。
Texture
Q:アーテイストによると、透過なチャンネルの画像があり、TGA形式である必要がありますが、透過なチャンネルがないため、PNG形式にすることはできません。Unityで透過なチャネルがあるPNG形式があるのは、なぜですか?どのようにしてアーテイストにPhotoShopでPNG形式の画像を作成させ、それでも効果を満足させますか? Unityの2つの図の違いの原理について詳しく説明していただけますか?
A1:PhotoShopにはPNG用の透過なチャンネルはありません。エクスポートしても、RGB3チャネルのみをエクスポートできます。PNGピクセルの透過度情報を変更するには、マスクを使用する必要があります。
アーテイストに、「この情報はマスクに描かれています。黒――透過、白――不透過であるように」のように伝えたら、理解してくれたと思います。
A2:TGAアーテイストを選んだ方が容易く処理もらえます。PNG形式の違いを気にする必要はありませんから。PhotoShopでAlphaを扱う必要もありません。結局のところ、エンジンはさまざまなプラットフォームに従って圧縮する必要があります。プロジェクトの規模に気にならない場合、より便利なプロセスが鍵となります。
Android
Q:ゲームを一定時間実行すると、以下のように一部のマシンがクラッシュします。皆もこのような状況に置かれることがありますか。
JNI ERROR (app bug): global reference table overflow (max=51200)
Unity 2018.3には関連するコンテンツがあると気付いたのです。今使用しているバージョンは2019.4.10で、修正されているはずですが、解答お願いいたします。
A1:JNIのコール回数が多すぎませんか?以前に試しましたが、Tencent Voice のAPI JNIを呼び出し続け、一定時間実行するとクラッシュします。問題主のおっしゃったのと同じようです。
A2:AndroidJavaClassとAndroidJavaObjectが頻繁にNewだけで、Disposeを呼び出さずにが発生するはずです。
A3:次の情報を参照してください。
2019.4.21f1 Release Notes
Fixes
Android: Fixed Java local reference leaking when using AndroidJavaClass/Object. (1283209)
https://unity3d.com/unity/whats-new/2019.4.21 のFixesに載っています。
AssetBundle
Q:AssetBundleロード方式の適用可能な環境に関して、AssetBundle.LoadFromMemoryおよびAssetBundle.LoadFromStreamの適用可能な環境は何ですか?
A1:AssetBundle.LoadFromMemory
UnityWebRequestによってダウンロードされたAssetBundleアセットを使用し、使用後にローカルに保存しないでください。
暗号化要件のあるAssetBundleアセット。
AssetBundle.LoadFromStream
暗号化要件のあるAssetBundleアセット(メモリ値は理論的にはAssetBundle.LoadFromMemoryよりも小さいです)。
Androidでは、StreamingAssetsディレクトリからコピーしてストリームを作成する必要があります。
A2:アセットを暗号化する必要がある場合は、最初にAssetBundleをメモリに読み込み、復号化してから、AssetBundle.LoadFromMemoryを呼び出してロードすることができます。この方法のメモリの最大使用量は、少なくともAssetBundleの2倍になります。「AssetBundleの原則とベストプラクティス」(中国語注意)を参照してください。
AssetBundle.LoadFromStreamはストリーミングモードでロードできます。すべてのAssetBundleをメモリに読み込んでから復号化してロードする必要はありません。代わりに、Bufferのようにその中で一部を読み取り、復号化することでロードできます。その方法はあまり大きなメモリを使用しませんから。このインターフェイスを使用する場合は、継承されたFileStreamクラスをカスタマイズしてから、ReadとWriteの方法でByte配列に対して、暗号化および復号化処理を実行する必要があります。
具体的な使用法については、https://www.xuanyusong.com/archives/4607を参照してください。
UWA Technologyは、モバイル/VRなど様々なゲーム開発者向け、パフォーマンス分析と最適化ソリューション及びコンサルティングサービスを提供している会社でございます。
今なら、UWA GOTローカルツールが15日間に無償試用できます!!
よければ、ぜひ!
UWA公式サイト:https://jp.uwa4d.com
UWA GOT OnlineレポートDemo:https://jp.uwa4d.com/u/got/demo.html
UWA公式ブログ:https://blog.jp.uwa4d.com
Author And Source
この問題について(UIにおいてSetActiveが大量に使用される問題), 我々は、より多くの情報をここで見つけました https://qiita.com/UWATechnology/items/a9dd6a6799bab5359d52著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .