ShaderLabのメモリ最適化

今回の主な話題：ShaderLabのメモリ最適化、Static Batchの使用に関する注意事項、foreachのMonoメモリ割り当て問題の修復、Unity 2017のシーンライティングのベイク情報が大きすぎ。

---
###レンダリング
Q1：Unity 2017で、社内のアーティストがベイクされたシーンライトマップには、Lighting Data Assetなどのファイルも含まれています。検索したらスタンプのサンプリング情報などのデータが含まれていることを示しています。大きくすべきではないですけど、現在のプロジェクトでは、このファイルは90MBに達し、シーンは非常に異常です。これをパッケージしなくで、インデックスから削除することを提案する人もいますが、そうすればシーンのライトマップは正常にロードできるのでしょうか。
>[こちら](https://docs.unity3d.com/Manual/LightmapSnapshot.html)で検査してください。下記のような文があります。
`The asset is an Editor only construct so far, so you can’t access it in the player. Currently, this file is a bit bloated as it contains data for multiple platforms - we will fix this. Also we are considering adding some compression for this data.`
ですから、90MBのすべてがバッグに入れられたわけではありませんが、中に保存されている必要な情報がバッグに入れられた後、具体的にどの大きさになるのは言いにくいです。一般的に、Precomputed GIを開かない場合には大きくないですが、「インデックスから削除」してパックすると、理論的にはライトマップが失われるので、動的にロードして設定する必要があります。

---
###メモリ管理
Q2：実機のテスト環境で、プロファイラーのメモリ使用状況を確認したところ、ShaderLabが大量のメモリを占有していることがわかりましたが、中に何がありますか？シェーダーバリアントを削減した後、この部分のメモリは減少し、Unityに組み込まれたStandard Shaderは使用されなくなりました。バリアントを減らずに、この部分が占めるメモリを減らすことはできますか？
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/30b90d11-733c-3e12-5506-5e2cee724bcc.png)
また、同じアイテムの下にあるオブジェクトが多くを占めていることもわかりましたが、なぜですか？![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/174e8fa6-646d-48a4-cc72-cfda2e4790be.png)
>ShaderLabは、プロジェクトがShaderをコンパイルするときに生成した分析バッファーです。このメモリ増加の特徴は、キーワードとバリアントが多いほど、メモリ使用量が大きくなることです。現在、バリアントを削減せずにメモリ使用量を削減する効果的な方法はありません。後で見つかったら、この部分を更新します。

>オブジェクトについては、検索して、前の関する答えを調べるとお勧めします。例えばこちらに（中国語注意）：https://answer.uwa4d.com/search/objects

---
###アニメーション
Q3：次の図に示すように、精度処理のためにアニメーションサフィックスファイルをインポートすると、一部の情報が失われました。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/a1501f3d-2539-5002-6161-d6d6e6d1c9f2.png)
変更されたコードは下記のように：

```ruby:
AnimationClip theAnimation = AssetDatabase.LoadAssetAtPath<AnimationClip> (path);
Keyframe key;
Keyframe[] keyFrames;
foreach (EditorCurveBinding binding in (AnimationUtility.GetCurveBindings(theAnimation)))
{
AnimationCurve curve = AnimationUtility.GetEditorCurve(theAnimation, binding);
if (curve == null || curve.keys == null)
{
continue;
}
keyFrames = curve.keys;
for (int i = 0; i < keyFrames.Length; i++)
{
key = keyFrames[i];
key.value = float.Parse(key.value.ToString(“f3”));
key.inTangent = float.Parse(key.inTangent.ToString(“f3”));
key.outTangent = float.Parse(key.outTangent.ToString(“f3”));
keyFrames[i] = key;
}
curve.keys = keyFrames;
theAnimation.SetCurve(binding.path, binding.type, binding.propertyName, curve);
```
>失ったのはmEditorcurvesです。このフィールドはanimがEditorに占めているメモリに影響しますのみ、実機で実行中のアニメーション効果とメモリ占有には影響しません。ですから、フィールドリストが空であるかどうかは、実際のデバイスでのパフォーマンスに影響を与えることはなく、質問を行う方法で正確に処理できます。このフィールドを保持したい場合（実機のメモリには影響はありませんが）、テキスト処理によってアニメーションファイルに対して精密処理を実行し、処理中にmEdtorcurvesフィールドをスキップできます。

---
###アセット管理
Q4：シーンにStatic Batchを使うと、使用されているすべてのモデルが大きなメッシュに合併され、ファイルとして保存されますので、シーンのAssetBundleが大きくなり、シーンのモデルファイルとファイルリソースが重複しているようになります。
もしシーンがStatic Batchをマークしなくて、ロード後にStatic Batchを動的に設定する場合、サイズを縮小できますか？
>そうです、Static Batchをマークすると、追加のCombined Meshデータが生成され、常により大きなサイズとメモリを占有します。Static Batchをマークしなくて、ロード後にStaticBatchingUtility APIを使って動的に設定するのも良い選択です。唯一の違いは、スペースコストの代わりにシーンのロード時間がかかっていることです。

---
###アセット管理
Q5：Unity5.6.4でforeachが引き起こすMonoメモリの割り当て問題が解決されましたか？
>Unity 5.6では、確かにforeachはMonoメモリの割り当てを生成しません。さらに、王さんのサプリメントのおかげで、この問題はUnity 5.5.5p1でも修正されました。

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

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