UnityでのShaderLabメモリの最適化

おそらく、ShaderLabメモリの最適化に困っている開発者は多いでしょう。「価格の高い」メモリスペースに、無視できないボリュームを占めることがよくあります。他のアセットメモリと比べて、「ブラックボックス」に似ているので、最適化するのは難しいです。そのため、いくつかの実験を通じてShaderLabの占有率を分析し、この部分のメモリを最適化する方法を考えました。

---
##一、問題を述べる
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/8e1ecae5-4891-a014-8009-abf7930e8c08.png)
上の図（戦闘シーンに入ったときのメモリスナップショット）から、ShaderLabの占有率が42MBに達していることがわかります。なぜ、ShaderLabの占有率がそれほど高いのですか？
##二、問題を分析する
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/574dec81-5ed2-4feb-0593-35f6d28c6331.png)
現在のアイテム（ShaderLab）には詳細なShader占有情報を説明していませんので、他の方法で原因を探さなければなりません。 幸いなことに、メモリスナップショットのAssetsの下のShaderアイテムに詳細な使用情報があります。

そして、StandardのShaderが使用されているのを見ましたが、このプロジェクトにStandardのShaderを使用する場所がありませんので、なぜ存在していますか？

究明のために、一輪の調査を回しました。Standardで使用されている場所のいくつかをクリアし、もう一度テストして、別のメモリスナップショットを作成しました。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/f7316fab-746a-7afd-5a4e-deda4b3380d7.png)
クリアした後、ShaderLabは27.6 MBに低下しました（後で、スタンダードは完全にクリアされ、21 MBに低下しました）。やっぱり、主な原因はStandardにあります。じゃあ、また問題が発生しました。Standardを使用していませんのに、なぜメモリにStandardが存在してありますか？

ここでは二点について話す必要があり、これもこの問題を排除する方法であります。
##三、問題を排除する
###1.モデルのインポートが導く
モデルをインポートする時、デフォルトで「Import Materials」がチェックされます。モデルがインポートされると、Unityは同じディレクトリに「Materials」ディレクトリを作成し、対応するマテリアルを作成します。このマテリアルはデフォルトでStandardを使用します。

アーティストが製造の過程にPrefabにあるモデルに他のマテリアルを添付しますので、実にはデフォルトのマテリアル（Standard）は使用されません。ただし、モデルをロードすると、デフォルトで作成されたマテリアルが再度ロードされ、シェーダーに解析され、メモリ内でStandardがあるになります。

では、ソリューションも非常に簡単です。「Import Materials」を削除し、使用されていないデフォルトのマテリアルを削除します。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/a5b5d4dc-bf09-2c18-f7c4-b78754306f3e.png)
**注：「Import Materials」を削除しないと、他のプロジェクトにインポートしたときにマテリアルがまた自動的に作成されます。**

**補足：**実際のプロジェクトでは、Prefabの変更回数は比較的多く、対応するモデルファイルの変更は比較的少ないため、プロジェクトのモデルと対応するPrefabは別々のAssetBundleにパッケージ化すると、非常に奇妙な状況が発生します。

「Import Materials」をチェックしないモデルファイルは、Prefabをインスタンス化すると、ShaderLabには一つの「Standard」のShaderメモリがありますが、このShaderの参照は一つの「Default-Material」ファイルに指します（しかしこのファイルは存在してありません）。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/ab458e45-aaa9-2ccf-baac-7077c75dc0ea.png)
ただし、モデルとPrefabが同じAssetBundleにあり、またはResourcesを使用してロードされている場合、「Standard」と「Default-Material」は顕示されません。Unity 5.3.3のバグなのか、Unityの特殊なメカニズムなのかはまだわかりません。

一時的な解決策：モデルをPrefabとは別にパッケージ化する必要がある場合は、「Import Materials」をチェックして、デフォルトで生成された材料を直接使用および変更します。

###2.デフォルトモデル（Cube、Sphere）の作成が導く
初期のシーンを構築する時、配置や視覚化しやすいのために、CubeみたいなシステムのデフォルトのMeshがアンカーポイントとして使用され、ゲームを始まる時に禁止させます。これらのCubeは有効になっていないため、パフォーマンスのコストはごくわずかであるため、無視します。

ただし、これはシステムのデフォルトのMeshであるから、作成時に指定されるマテリアルはデフォルトのマテリアル「Default-Material」であり、このマテリアルで使用されるシェーダーはたまたま「Standard」です。だから「Standard」の存在は間違いではありません。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/44a91b50-4cfa-7804-34d6-d5e33718fb89.png)
解決策も非常に簡単です。これらのMeshを削除するか、マテリアルを交換します。 こうすれば、この部分が占める「Standard」は存在しません。
##四、まとめ
Standardの変種が多すぎるため、Standardを使用しますと、複数のStandardの変種が同時に存在することがよくあり、大量のメモリを占めます。ShaderLabのメモリが大きすぎと感じっている場合は、上記の原因ですかどうかを調べてみてください。

ShaderLabのメモリ占用が大きすぎとは、完全にStandardの原因ですか？実際にはもっとあります。最適化後の27MB（完全にクリアされた後の21MB）の中に、他の原因があるはずです。しかし、最適化の過程は大きな部分から削除し始まることです。上記のように、少し最適化したら20MB以上を改善できますし、もちろんすぐにやる必要がありますが。サイズが小さいほど最適化効率は低くなるので、現時点では 「Assets」や「Texture2D」などの部分に目差して最適化します。したがって、残ったShaderLabの最適化方法は後であった時に再び補充します。



**PS：上記の全ての内容は実機でテストしました。**

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

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