UnityアセットAPIアンインストールのテクニック

今回の主な話題：「UnityアセットAPIアンインストールのテクニック」、「Reserved Total Unityメモリ変化問題」、「MangedHeap.UseSizeの値は変化している」。

---
###メモリ
Q1：私かAssetBundleをロードするのため、一つのケースを書きました。複数の特殊効果Prefabをシーンにインスタンス化します。複数回のケースを 実行し続いて、付加された特殊効果対象を全部削除し、シーンを替えますと、Profilerにのメモリ変化が次の図のように見られます：
![１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/d56a8710-d90f-95c0-d426-8fb07a040d0e.png)
聞きたいのは：
1. Profiler内のReserverd UnityメモリはUsed Unityメモリよりかなり高いのが正常ですか。
2. 正常であれば,Reserverd Unityメモリを回収する方法はありますか。
3. 上記のようにケースを複数回実行された後、Reserverd Unityメモリは400MBに安定していますが、もう1一度ケースを実行したらメモリは450MBまで上昇し、後に400MBまで下がました。このような表現も正常ですか。
>1.このデータはエディターでテストした結果ですか。ReserverdはUsedよりこんなに高く超えるのは確かにあまり合理的ではありません；ただし、エディターですれば、実にUnityはたくさんの補助操作を行って、これらもメモリを占用します。ですから、実機でテストをやってみますとアドバイスします。この格差は下げられますかどうかを観察してください。しかし、実機であれば、その差は確かに高すぎて、あまり合理的ではありません。
>2.Reserverd Unityのメモリはエンジン自身が管理しています、一般的にその後もう使用しない時に自分から下げます。
>3.このような上昇や転落は普通ですが、こんなに高いかどうかは、問題1の回答を見てください。

---
###メモリ
Q2: Resources.UnloadUnusedAssets()が旧シーンをアンインストールした後、新シーンをロードする前にコールすればいいですか。それとも新シーンをロードしたらコールすればいいですか。メモリMaxを考えると前者の方がいいと思いますが、UWAにUWAにある文章はシーンをロードする後にコールの方がいいと肯定しました。
>もし問題主はLoadLevel(Async)のような方式でシーンをロードすれば、Unity自身は最下層にResources.UnloadUnusedAssetsみたいな操作を一回行います。この時手動的にResources.UnloadUnusedAssets操作をコールすれば、時間間隔は短いです。これは実に少し重複しています。そのため、新シーンをロード後に再びコールするとアドバイスします。
しかし、もし問題主はLoadLevelAdditiveや似たようなAPIでシーンを替える場合には、UnityはResources.UnloadUnusedAssetsをコールしません。それで旧シーンをアンインストールしたからコールするのもいい選択です。

---
###レンダリング
Q3：ShaderにのBlend OffとBlend One Zeroは完全に等価であると認められますか。UnityのStandard Shaderに見られますのは、ブレンドはBlend [_SrcBlend] [_DstBlend]のようなもので動的にコントロールされています。そしてStandardShaderGUI.csにOpaqueを設定する時、設定されたのはBlend One Zeroでした。ですからShaderにBlend One Zeroを入れったら、Blend Offと等価であると認められますか。Unityはdestbufferからデータを読み込めない為に自動的にblendstateを変えますか。
>私たちはUnity 2017.１でテストしました。実にはAndroidプラットフォームのGLESコール中、UnityのStandard ShaderのOpaqueモードがdisable blendの状態でレンダリングされていますと発見しました。実験は下記のように：
設備：Red mi 2。レンダリングシーンは2つのStandard Shader Opaqueモードオブジェクト(SphereとCube)であり、間にUnlit Transparent Quadがあります。
![２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/1324b2da-1c3a-98cf-ec18-d373ce652ece.png)
AndroidツールでGLES APIコールを見ますと,CubeとSphereをフレームごとにレンダリングする際にBlendはオフ状態(前フレーム終了時にオフ)であり,Unlit TransparentのQuadをレンダリングする際に開きます。
![３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/f54847e4-3462-e458-01c0-1c7e3b9254b1.png)
この中に,36個頂点のDCはレンダリングCube, 2304個頂点のDCはレンダリングSphere, 6個頂点のDCはレンダリングquadであります。ですからStandard ShaderのOpaqueモードはglDisable(GL_BLEND)状態でレンダリングされるはずです。

---
###メモリ
Q4:ゲームに毎回ステージをクリアしてホームに戻る時、メモリデータはいつも不一致です。Unity Profilerを通じてManagedHeap.ReservedUnuseSizeとManagedHeap.UseSizeの値はずっと変化していますと観察されました。この変化は合理的ですか。
>ReservedUnuseSizeとManagedHeap.UseSizeはずっと変化していますのは正常です。いずれもMonoメモリに属しており,前者は現在のMonoメモリが使用されていない部分です,後者は現在使用されている部分であります。一般的に、ゲーム内のMonoメモリはコードで割り当てられています。ですからこの二つの値はいつも変化していますのは正常な状況です。

>ここで問題主に以下の2点に注目することを提案します。

>⑴総Monoメモリはずっと上昇していますか。

>下記の図にはUWAパフォーマンスレポートのMonoメモリの傾向グラフです。紫色の線はプロジェクト実行中のManagedHeap.UseSizeであり、黄色の線はReservedUnuseSizeです。両者ともずっと変化していますが、最も注意すべきのは青い線のReserved Monoであります。この線が上に行くと,プロジェクトにはメモリリーク問題がある可能性が高いので,開発チームに精査すると提案します。
![４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/df045733-8532-05ab-28f8-a96ea1532f06.png)
⑵具体的なMonoメモリの割り当ては合理ですか。

>ManagedHeap.UseSizeやMono総メモリはコードのMonoメモリによって上昇していますから、コードMonoメモリの割り当ての合理性をチェックし、必要のないMonoメモリ割り当てを避けるのは大事なことです。下記のように：
![５.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/7bfd2776-3e7f-fef7-b2c0-67e22809ce58.png)

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

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