fall and fall

Unityやゲームのことなどを書いています。

Unity 画像を動的に読み込んでメモリを解放する方法

Unity の Resources を使って、テクスチャを動的に読み込んで、使用後にメモリを解放する方法を書いていきます。

動作確認

以下のゲームで動作を確認しています。

注意点

Unity のチュートリアル には「Resources を使用しないでください。」と書かれています。

チュートリアルの「3.1. Best Practices for the Resources System」で「Don't use it.」。

Resources を使うメリット

Resources を使うメリットは以下の通りです。

  1. 画像を読み込むまで、メモリ消費を抑えることができます。
  2. 画像のメモリを解放することができます。

1. Resources フォルダの準備

Assets の下に Resources フォルダを作成して、読み込む画像を置きます。

2. SpriteRenderer の作成

Resources フォルダの画像をヒエラルキーにドラッグ&ドロップして、SpriteRenderer を作成します。

今回は4つの画像を追加しています。

必要に応じて SpriteRenderer の Position を調節しておきます。

3. Sprite の削除

インスペクターで、SpriteRenderer の Sprite を削除します。Sprite の値をクリックして Delete を押すと削除できます。

削除すると、画面の画像も消えます。

Sprite を削除しないと、ゲームの起動時に画像がメモリに展開されます。なので、今回は全て削除しました。

4. スクリプト作成

スクリプトを作成して、以下の内容を保存します。Enter を押すと画像を読み込んで、再度 Enter を押すとメモリを解放します。

Controller.cs

using UnityEngine;

public class Controller : MonoBehaviour {
  public SpriteRenderer[] renders;
  string[] paths = {
    "marisa", "pache", "reimu", "sakuya"
  };
  bool loaded = false;
  void Update() {
    if (Input.GetKeyDown(KeyCode.Return)) {
      if (loaded) Unload();
      else Load();
    }
  }
  void Load() {
    for (int i = 0; i < renders.Length; i++) {
      renders[i].sprite = (Sprite)
        Resources.Load(paths[i], typeof(Sprite));
    }
    loaded = true;
  }
  void Unload() {
    foreach (SpriteRenderer sr in renders) {
      Resources.UnloadAsset(sr.sprite.texture);
      sr.sprite = null;
    }
    loaded = false;
  }
}

画像の読み込み

画像を読み込む際は、Resources フォルダの画像のパスを指定します。

Resources.Load(paths[i], typeof(Sprite));

メモリの解放

メモリを解放する際は、null の代入がポイントになります。

Resources.UnloadAsset(sr.sprite.texture);
sr.sprite = null;

5. スクリプトの有効化

空の GameObject を作成して、スクリプトをアタッチします。

スクリプトの public変数 renders には、先ほどの SpriteRenderer を全て紐づけておきます。

6. 動作確認

ゲームを起動して、Enter で動作確認します。

画像読み込み後

プロファイラのテクスチャは 220 で、21.0MB でした。

メモリ解放後

テクスチャは 216、5.0MB になりました。

ゲーム起動直後は、この値に近かったです。

参考文献

unity_script_get_resources_object - FreeStyleWiki