WaitForGPUを最適化する方法

今回の主な話題：WaitForGPUを最適化する方法、DrawMeshInstancedで各オブジェクトに異なる色を指定する方法、UnityがモデルをインポートするときにオプションSwap UVsの役割、キャラクターの服替えモデルの合併問題。

---
###レンダリング
Q1: 最近、Unity 5.6.3バージョンを使用して開発したVRデモを作成しましたが、モデルの詳細を近距離で観察すると、突然非常に重くなることがわかりました。フレームレートが95FPSから45FPSに低下しました。

下図には、一般的な距離でモデルを観察すると問題なく、フレームレートが正常であります。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/e232d868-2890-aa11-cc48-99aca6af4aff.png)
下図には、近距離でモデルを観察すると、フレームレートが大幅に低下し、VR.WaitForGPUの割合は非常に高くなります。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/de53de70-f7fa-27d5-a706-13a5a235eb2f.png)
これはどうしてですか？
>ALUの問題により、GPUの圧力が高くなりすぎると推定します。根本的な原因は、モデルのFragment Shaderの命令セットが高すぎることです。その結果、UWA Day 2018でやったStandard Shader画面占有実験のように、レンダリングされるピクセル数が多いほど、GPUオーバーヘッドが高くなります。ローエンドデバイスでは、画面が20％以上を占め、GPUに20ミリ秒以上かかります。
![3-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/3f3a2108-4329-df85-ab02-506c2690f758.png)
![4-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/f5b9138b-2c22-7413-6fbc-ceb0f9ef82f7.png)
WaitForGPUが高すぎるため、現時点でGPUがパフォーマンスのボトルネックになっていることを示しています。 これに関して、問題主に自分が遭った状況はこのようなことかどうかを確認することをお勧めします。

---
###制作
Q2: Unity公式に下記の内容が書いてあります。

Swap UV channels in your Meshes. Use this option if your diffuse Texture uses UVs from the lightmap. Unity supports up to eight UV channels but not all 3D modeling applications export more than two.

但し、この説明によくわかりません。自分が試してみると、ライトマップを使用しているかどうかに関係なく、このオプションをオンまたはオフにしてもモデルは変更されませんでした。どのような状況でそれをチェックする必要がありますか？UVチャンネルを交換するとはどういう意味ですか？
>前のドキュメントにある説明：Swap UV：Use this if lightmapped objects pick up the wrong UV channels. This will swap your primary and secondary UV channels.
今のドキュメントにある説明：Use this option if your diffuse Texture uses UVs from the lightmap.

>そして、こちらにこのオプションについての議論を参照できます：https://forum.unity.com/threads/poll-is-swap-uvs-mesh-import-setting-useful-for-anyone.173468

>見るだけではLightmappedモデルのテクスチャが混乱してしまった時にのみ使用します。例えば一部のモデリングソフトウェア（blenderなど）からインポートされた複数のUVチャネルを持つモデルなど。

---
###レンダリング
Q3: DrawMeshInstanced APIを使用して複数のオブジェクトをレンダリングする場合、各オブジェクトに異なる色を指定する方法はなんですか？このインターフェイスのパラメータにはMaterialPropertyBlockがありますが、これは配列ではなく、複数の色を指定することはできません。
>このインターフェイスを使用せずにシーンにオブジェクトを配置する場合は、確かにオブジェクトごとにカラープロパティが異なるMaterialPropertyBlock指定することで実現させられます。
>ただし、このインターフェイスを使用したら、指定できるMaterialPropertyBlockは1つだけなので、SetFloatArrayなどの配列を準備して、Shader内で配列内の値を使用して対する値を色として取得（または計算）することができます。

---
###制作
Q4：モデルの合併またはキャラの服替えに知っていますか？合併を2回した後、2回目合併後のUVが間違っていますが、何か解決する方法はありませんか？

たとえば、A（aMat）、B（bMat）、C（cMat）、D（dMat）の4つのコンポーネントがあります。
1）CombineMesh（coms、true、false）を初めて使用して、A、B、およびCメッシュ（combineMesh1）を合併し、マテリアルatlasMatと統合します。
2）2回目のCombineMesh（coms、false、false）を使用して、combineMesh1、Dメッシュ（combineMesh2）を合併し、マテリアルを同じRendererに移動します。

最後に、ABCDはすべてcombineMesh2に統合され、Rendererのテクスチャは2（atlasMat + dMat）になります。dMatのUV表示が正常ではありません、これはどうしてですか？
>Meshが1つしかない場合、複数のMaterialが問題を引き起こします。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/bef1f731-1969-7cba-5ce5-da9c1f633128.png)
また、1セットのUVが2セットのテクスチャに対応しているため、表示が異常になります。DメッシュのUVをUV1（UV2、UV3、UV4）に変更できますが、dMat Shaderを変更する必要があり、DrawCallも追加されます。
または、dMatテクスチャと共にatlasMatに合併することもできます。

---
###パーティクルシステム
Q5: Unityバージョン2017.1.3を使っています。特殊効果スタッフがパーティクルシステムのtrailsモジュールを使用し、テールを形成するためにworld spaceを使用しました結果、ゲーム内でパーティクルバウンディングボックス全体的な計算に問題があって、カリング操作中のエラーを起こしました。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/70f4b341-3a3d-edcf-fc6c-ccef5186edbc.png)
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/e223c810-5360-8893-3443-67168f22b133.png)
>一つのCullingGroupを使用して解決策を見つけました。CullingGroupの可視性を使用して、パーティクルシステムを調整することです。具体的な方法は次のとおりです。
1）パーティクルシステムの座標位置にCullingGroupを配置し、包囲球の半径を設定します。
2）CullingGroupの可視性およびonStateChangedイベントを使用して、パーティクルシステムの可視性を更新します。

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

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