Unity UIの表示と非表示（共存）関係最適化処理案

今回の主な話題：Unity UIの表示と非表示（共存）関係に関する最適化処理案、UWA GOT OnlineのLua分析、シーンがAssetbundleするとパッケージサイズが増加する、iPhoneの下部にある水平バーを非表示にする方法、NativeコードにSkinnedMeshRendererのボーンTransformをどうやって設置する。

---
###UI
Q1: Unity UIの表示と非表示（共存）関係の最適化案に関して、一般的にどうやって処理しますか？

１、状況説明
シーン1：ポップアップウィンドウAに１つのボタンがあります。クリックすると、ポップアップウィンドウBを開き、ポップアップウィンドウAを閉じる（または閉じない）ことができます。

シーン2：ポップアップウィンドウCに１つのボタンがあります。クリックすると、全画面パネルを開き、他のすべてのUIが非表示（破棄）になります。
……

2、問題説明
類似な問題はOverdrawのインジケーターに影響します。表示と非表示の関係が適切に行われていないと、レンダリングの拡大率が高くなりすぎます。また、UI表示ロジックが不合理になり、管理が困難になります。

先輩たちはこのような問題をどのように処理しますか？

①
>このような問題は、プロジェクトごとに具体的な要求が違う可能性があります。プランナーのロジック性がより強い、責任を取るUIプランナーもいる場合、最善の方法はプランナーに要件を整理させ、プログラムが戦略を作成することをお勧めします。
>
ここで説明した要件には、通常、次の問題が含まれます。
>
一、閉める方法
1、無制限に戻します。つまり、繰り返す開ける3つのインターフェイスABCがある場合、何度も開いた後、戻るボタンを介して開いた順序で同じ回数を戻ってから、メインインターフェイスに戻れます。（崩壊3はこのようなものであることを覚えました。）
2、インターフェイスを閉じます。一番目の方法と違って、ABCを複数回開いても、1回閉じる限りインターフェイスは閉じられます。
>
二、オープンメソッド
AからBを開き、Aを閉じる必要があるかどうか、つまり、Bを閉じた後にAに戻るか、メインインターフェイスに戻るかを指定します。ここにも「ABが両方フルスクリーン」、「ABが両方ポップアップウィンドウ」、「ABの1つがフルスクリーン、もう1つがポップアップウィンドウ」の状況に関します。
>
三、特殊効果、３Dモデルのレイヤー問題
2D + 3Dの表示状況では、複数のUIにインターリーブ問題がある可能性があります。これにも考慮する必要があります。
>
四、ステージ終了時の表示UI
ステージから出ると、入る前の状態を表示する必要がありますか。
>
五、ナビゲーション共有
すべてのUIが同じナビゲーションを共有するのか、それとも各インターフェースが別々に行われるのか。
よく見られるのは以上です。要件が明確になったら、管理方法を見ていきます。
>
私たちのプロジェクトのやり方はスタックを管理することであり、そのほとんどはフルスクリーンUIであり、これが前提です。全てのUIを１つのスタックに、フルスクリーンのUIを１つのスタックに、またはフルスクリーンUIに一番上のスタックのみが表示されます。私たちのプロジェクトでは、ポップアップUIがフルスクリーンUIの下にある状況はほとんどないため、この部分の個体的なOverdrawには耐えます。これはプランナーとのコンセンサスであります。
>アンインストールは配置によってコントロールされます。システムに複数のインターフェイスがある場合、システムのエントリインターフェイス、つまりシステムのメインインターフェイスが閉じられる時に、このシステムのすべてのUIをアンインストールします。通常、システムにはいくつかの共有アトラスがありますから、ロジック上はより合理です。もちろん、具体的にどのようなシステムまたは重要さにも関係あります。イベントにある運営サイトにログインする際のインターフェイスなどは、閉じられるところにアンロードされます。

>SetActive方式を使用して遮られたUIを表示/非表示にするためのいくつかの注意事項を追加します。
１、OnEnable / OnDisableに重要なロジックを書くないでください。
２、Updateに書いたロジックに注意してください。
３、NGUIのButtonの状態が異常になる状況に遭うことがあります。

②
>フルスクリーンページ（以下、フルスクリーンと呼びます）とウィンドウページ（以下、ウィンドウと呼びます）を区別しました。フルスクリーンとウィンドウの両方がUIを独占するという大前提があります。開いた後は、下の方はクリックできません。同時に表示されるフルスクリーンディスプレイは1つだけです。ウィンドウが同時に重なりすぎないようにします。フルスクリーンを開くと、前のフルスクリーンページが閉じます。ウィンドウを開くと、ウィンドウは現在のフルスクリーンに依存します。ウィンドウはフルスクリーンのSubItemであり、どこで開いたウィンドウでも、フルスクリーンのノードの下に作成されます（フルスクリーンノードの構造は統一されています）。現在のフルスクリーンを閉じると、依存するすべてのウィンドウが解放されます。ウィンドウを閉じるときは、自分だけを離すと同時に、フルスクリーンの引用を削除します。
>
プログラムには、フルスクリーンの開く順序を記録するためのスタックがあります。フルスクリーンを開くたびに、一つのtypeをスタックに圧縮し、戻る時にはスタックにある順序で正常に戻ると、ターゲットのフルスクリーンにロールバックできます。つまりスタックからターゲットタイプに到達するまでです。フルスクリーンを開くときは、デフォルトで開くか、UIDataでターゲットのフルスクリーンデータを設定できます。ターゲットフルスクリーンを開いた後、tagの切り替えやウィンドウの開きなど、UIDataのデータに従ってフルスクリーンを初期化できます。

③
>
UIの表示に最適化を行いすぎないでください。多すぎる最適化とカプセル化は逆に簡単な問題を複雑化させます。時間もかかる、ロジックを混乱させ、学習コストも増加します。最も原始的なソリューションを使用して複数のLayerを分割し、それらを表示する必要がある場合は直接SetActiveを行います。一つの簡単な、関連なく、理解しやすい表示システムだけが、様々な要件に満たさせられます。

---
###Lua
Q2: UWAGOT Onlineツールを使用して、Luaメモリを検出しました。このようにDestroyed総数が0を超えていますが、このデータから何かですかもわからずものにどのように処理しますか？
![1-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/ae11c893-d84b-1428-442d-2b1421fd0125.jpeg)

>Destroyedことは、Unityによって「破棄」されたが、またCacheに引用されているオブジェクトの数を意味します。総数が安定している場合、問題は大きくありません。しかし、それが増え続ける場合は、確かにそれをローカルすることを試みる必要があります。
>
SLuaに組み込んであるMemory Profilerは、この部分のデータの強化バージョンと見なすことができます。Destroyed前に、各オブジェクトの関連コンポーネントまたはGameObjectの名前を記録し、トラブルシューティングに便利です。ToLuaまたはXLuaの場合、SLuaの実現を参照して自分で作成する必要があるそうです。原理は似ているため、コピーする方が簡単です。
>
これらの2つの関数は、SLuaコードで直接検索でき、アイデアを確認できます。

>```ruby:
ObjectCache.GetAlreadyDestroyedObjectNames();
ObjectCache.GetAllManagedObjectNames();
```

---
###アセット管理
Q3: 最近、プロジェクトでシーンをAssetBundle（以下、AB）にパッケージ化すると、パッケージのサイズが非常に大きくなることがわかりました。分析の結果、アセットの重複が問題であることが判明しました。 具体的な状況は次のとおりです。

シーンA、B、CはそれぞれPrefab Mを引用しています（MにはテクスチャT1、T2などの他のアセットが含まれています）。現時点では、私たちのパッケージ戦略によって分析すると、最終的にAu、Bu、Cu、Muの4つのABパッケージが印刷され、問題がないはずです。しかし、これら4つのパッケージを確認したところ、テクスチャT1やT2などの共有依存Mにあるアセットは、これらの４つのABパッケージに削除されて引用のみが保存されたではなく、それぞれに1つのコピーがあり、パッケージサイズをより多くなさせます。最後に、自分が実験した結果は、シーンをパッケージするとき、Mにあるアセットを単独にパッケージする場合、つまり、A.u,B.u,C.u,M.u,T1.u,T2.uをパッケージ出す状況にのみ、アセットの重複が避けられます。

ただし、明らかに、   この方法でABをパッケージ化する粒度は細かすぎます。私たちのプロジェクトには多くのアセットがあるため、ABをパッケージ化する数は急激に増加しますが、あまり良い方法ではありません。目前、この問題はシーンABでのみ発生します。他のタイプのABのパッケージ化は繰り返しません。 Unity 2017.4.1f1（64ビット）バージョンを使用しています。

このような問題に遭ったことはありませんか？どうすればいいですか？

>Sceneに対して、Prefabは元々Clonefor Sceneであり、Refではないため、パッケージ化する際にPrefabとはまったく関係がありません。例えば、Scene A、B、CがPrefabDを引用し、パッケージ化時にDのコピーがA、B、およびCに複製されます（Editorで編集する場合のみ、ref + changeとして保存されます）。つまり、Prefab Dは完全にパッケージ化する必要はまったくなく、パッケージ化されていても、シーン内のcloneとは関係ありません。したがって、pfbを共有ユニットとして使用することはできません。また、Prefabとsceneが引用するTextureはRefであり、これは共有ユニットとして使用できます。
>
1つの解決策は、Unity 2018にアップグレードすることです。新しPrefabメカニズムにより、SceneのPrefabはcloneではなく、Refになさせます。これは、他の人が言及しました、私自身はテストしたことはありません。

---
###UI
Q4: iPhone Xの下部にある水平バーを非表示にする方法は？
>バージュン2017にこの二つのオプションがあります。
![2-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/628dff5a-96a7-7b9e-9c99-6d6dfe3b8bac.jpeg)
上記のオプションがない場合は、エクスポートされたXcodeプロジェクトのこちらを変更できます。（このコードがない場合は、追加するだけでいいです。）
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/3ad31498-eb1c-25a6-74ed-adaa609449b6.png)

---
###Animation
Q5: 要件があるため、NativeコードにSkinnedMeshRendererのボーンTransformを設置したいです（Unityバージョンに制限はありません）。現在見られる方法は、OptimizeGameObjectを使用せずに各ボーンのTransformを直接変更することです。OptimizeGameObjectの場合にボーンノードを設定する方法はありますか？
>DynamicBoneとOptimizeGameObjectが共有できないと同じに、一般的な方法は無いはずです。少数のボーンノードを設定したい場合、先にExportすることが試せます。しかし、多数またはランダムなボーンノードである場合、おそらく到達する方法はありません。

---
UWA Technologyは、モバイル/VRなど様々なゲーム開発者向け、**パフォーマンス分析**と**最適化ソリューション**及び**コンサルティングサービス**を提供している会社でございます。

UWA公式サイト：https://jp.uwa4d.com
UWA公式ブログ：https://blog.jp.uwa4d.com