個人で勉強しているうちは気にしていなかったのですが、実務として扱うようになるなり勉強が必要となりました。
Unityのプロファイラーで学んだことを下記へまとめていきます。
##動的に生成したTextureとSpriteはしっかり管理しよう!
参考:
動的に生成したTextureとSpriteはしっかり管理しよう!
【Unity】アセットのUnloadとDestroyについて
タイトルの通り、Texture2DとSpriteを動的に生成する処理は、コンポーネントしているGameObjectがDestroy(破棄)されてもTexture2DとSpriteが残ってしまいます。
使わないリソースを破棄する方法は例えば、
- Resources.UnloadUnusedAssets()を使用する
- foreachで個別にDestroyする
###Resources.UnloadUnusedAssets()
Unityスクリプトリファレンス
使用していないアセットをアンロードします。
ヒエラルキーにあるゲームオブジェクト(スクリプトコンポーネントを含む)群で総なめして、アセットが使用されていないかを判断します。静的変数も調査されます。
しかし、スクリプト実行スタックは 探索されない ため、アセットはスクリプトスタックの中からのみ参照されるため解放され、必要であればそのプロパティーやメソッドのひとつが使用されるときに再び読み込まれます。これはメモリ上で修正されたアセットの場合は特に扱いに注意が必要です。アセットのガベージコレクションがトリガーされる前に EditorUtility.SetDirty を忘れずに呼び出しをするべきです。
Resources.Unloadは,例えばProfilerのMemoryの項目でAssetsと表示される項目をアンロードできます。
それ以外の項目、NotSavedやSceneMemoryに格納される、インスタンス化したオブジェクト群はResources.Unloadでは開放する事が出来ません。これは、実行時に値を変更したMeshやMaterialや動的に生成したTexture、Prefab等が該当します。
###foreachで個別にDestroyする
NotSavedやSceneMemoryの項目に格納される、インスタンス化したアセットに関しては、個別にDestroyで開放します。
public class CreateTexture : MonoBehaviour {
public int m_createCount = 100;
private List<Texture2D> texture2dList = new List<Texture2D>();
private List<Sprite> spriteList = new List<Sprite>();
// Use this for initialization
void Start () {
for(int i =0; i < m_createCount; i++)
{
Texture2D texture2D = new Texture2D(1000, 1000);
Sprite sprite = Sprite.Create(texture2D, new Rect(0.0f, 0.0f, 1000, 1000), Vector2.zero);
texture2dList.Add(texture2D);
spriteList.Add(sprite);
}
DestroyTexture2D();
}
private void DestroyTexture2D()
{
Destroy(this.gameObject);
}
private void OnDestroy()
{
Resources.UnloadUnusedAssets();
}
}
Memoryプロファイラーを使用します。
ゲームを実行→アセットがロードしているか知りたいタイミングでTake Smaple: Editorを押す。
→Scene Memoryの中から目当てのアセットを探す。
私の場合は、Texture2Dの画像でした。
例えば、画面遷移後にもう一度TakeSampleし、この画像がなくなっていたならば、意図通り破棄できたと確認できます!
##ガベージコレクション
ガベージコレクションは、不要になったメモリ領域を自動的に解放する機能です。
Unityのガベージコレクションはあまり高性能ではないらしい。