Cygames Tech Fes フォローアップ: Unityにおけるメモリ管理


みなさん、こんにちは!
Cygamesエンジニアの高原です。
先日のCygames Tech Fesには多数の方にご来場いただき、ありがとうございました。
当日はトラブルもあり、駆け足での説明になってしまい申し訳ありませんでした。
この場を借りて少しフォローをさせていただきます。

どうして参照にnullを入れる必要があるのか?

UnityのObject型は演算子のオーバロードを行っていて、

public static bool operator !=(Object x, Object y);
public static bool operator ==(Object x, Object y);
public static implicit operator bool(Object exists);

Destroyされるとnull比較時にtrueを返す実装になっているのが原因になります。
要は実体は残っているのに、外部にはnullであるかのように装っているわけです。
そのため、使わなくなったオブジェクトへの参照はnullを明示的に指定してあげなければいけません。

メモリ管理で気をつけていること

懇親会で質問があったのでここでも触れたいと思います。
メモリ管理する上ではピーク使用量を抑えるのが大事になります。
では実際どのくらいまで使えるのか?

以前 こちらの記事 で「iOSで350MB〜600MBくらい」という風に言われていますが、
IL2CPPが有効になったせいで使用可能なメモリが減ってるようです。
この辺りUnityのバージョンでも差が出ると思いますので、自身の環境で計測することをオススメします。

計測の仕方ですが、ボタンを押すとメモリを確保するアプリを作って、何回目でクラッシュするか?を調べました。
メモリ確保方法はnewでもAssetBundle.Loadでも結果はほとんど変わりませんでした。

さて、これでメモリのピーク使用量がわかったので、メモリの配分を考えなくてはいけません。
キャラクター1体あたり ○MB × 10体、背景○MB、UI○MB…
といった具合に使用量の見積もりをしておくとよいでしょう。

ここで注意したいのはMonoのメモリ使用量です。
MonoがOSから確保したメモリは解放されないため、一度にメモリを確保するとその後の使用可能なメモリが減ったままになってしまいます。
ありがちなのがIO関連で、ファイルダウンロードがあるとその後のプレイ中にアプリがクラッシュするといった事例がありました。

以上「Unityにおけるメモリ管理」の補足となります。
みなさまのお役に立てば幸いです!