Unityで開発するならば、基本的にメモリ管理はUnity側で行ってくれる(参照しなくなったリソースなどのデータはメモリから解放する)ため、開発者はメモリ解放ためのコードを書くなどのメモリ管理をしなくても良いのです。
しかし、困ったことにTextureなどの一部のリソースデータは、どのゲームオブジェクトから参照されていなくても解放されていなかったのです。
Textureも含めたリソースデータもメモリから解放したい場合は、シーンごとを削除することです。
この記事では、
・メモリーをシーンで管理する
・Resources.UnloadUnusedAssetsで使われていないアセットの解放
について解説します。
メモリーをシーンで管理する
概要
Unityにはシーンという機能があります。
SceneManager.LoadScene(“シーン名”)関数を使って、次のシーンの遷移すると遷移前のシーンを削除することができます。その結果、前のシーンで確保していたメモリー解放してくれます。
問題になっていた、Texture分のメモリも解放してくれます。
Textureは、Unityの仕組みで要らなくなってもUnity側でキャッシュしているようです。
profiler確認してみると、どのゲームオブジェクトがテクスチャを参照していなくても消えていないことがわかりました。
≫ゲーム業界最強のマッチング力【シリコンスタジオエージェント】
実際の切り替えについて
シーン1からシーン2に切り替え方法と、メモリ上の挙動を解説します。
(1)アプリ起動などでシーン1をロードする。
(2)シーン2を読み込む
以下の関数を呼び出してシーン2を呼び出す
SceneManager.LoadScene(シーン2″);
(3)シーン2を読み込んだあとの挙動
シーン2を読み込んだあとシーン1は、Hierarchyから消えていることがわかります。
シーン1で確保していたデータ(Textureなどのリソースも含む)は、メモリーからされています。
上記はシーン1解放前です。Textureで357.7M使っていることがわかります。
シーン2に切り替えたときの画像です。シーン1が解放されたためTextureのメモリは24.4MBになったことを確認できました。
その結果、シーン1のデータがメモリから解放された。
シーン1、2で共通にデータを使いたいとき
シーン1で使っていたデータをシーン2でも使いたいケースがあります。その様なときは、static変数にデータを入れます。
static変数のデータは、アプリを終了するまでは解放されません。よって、どのシーンでも共通にデータを使いまわしたいときは、static変数に格納しておくと良いです。
Resources.UnloadUnusedAssetsを使う
Resources.UnloadUnusedAssetsを使って、使用していないアセットをアンロードします。
この方法でもメモリ解放できるようですが、実際に使ってみたところ、どこからも参照されていないはずのTextureは、メモリから解放されていませんでした。Unityは、一度メモリーにロードしたTextureを本体側でキャッシュしているようです。
不要なTextureも削除したいのであれば、(1)で解説したようにシーンごと削除する必要があるといえます。
まとめ
Unityで開発するならば、基本的にメモリ管理はUnity側で行ってくれる(必要が無いデータはメモリから解放する)ため、開発者はメモリ管理を意識しなくても良いのです。
しかし、意識しなくても良いからと言って、メモリを常に増幅させるようなプログラム(例えば、1シーンでプレイヤーの行動によってゲームオブジェクト生成し続けるようなもの)を書いていれば、メモリ不足が発生して強制終了などの不具合に繋がります。
どこでメモリを解放させるのかは、意識して開発を進めた方が良いと言えます。
≫ゲーム業界最強のマッチング力【シリコンスタジオエージェント】