Renderer.materialで取得したマテリアルは自分で破棄しないとリークするというお話です。
Unity2018.4.6
Renderer.material?
Renderer.material
にアクセスするとレンダラのマテリアルを取得できます。
このとき、マテリアルがこのオブジェクト用に複製されます。
Renderer.materials
も同様です。
なお、代わりにRenderer.sharedMaterial
を使うとマテリアルが複製されず元のマテリアルを参照します。
自分で破棄しないとリークする
さてこのようにRenderer.material
を通して取得したマテリアルは、自分で破棄しないとリークします。
マニュアルにも以下のように明記されています。
It is your responsibility to destroy the automatically instantiated mesh when the game object is being destroyed
したがって、Renderer.material
を使った場合にはそのマテリアルをOnDestroyなどで破棄する必要があります。
using UnityEngine; public class Example : MonoBehaviour { private Material _material; private void Start() { _material = GetComponent<Renderer>().material; } private void OnDestroy() { if (_material != null) { Destroy(_material); } } }
実用性を考えると次のようなコンポーネントをRendererを持つオブジェクトにアタッチするのがいいかもしれません。
using UnityEngine; [RequireComponent(typeof(Renderer))] public class Example : MonoBehaviour { private void OnDestroy() { // 複製されたマテリアルをすべて破棄する foreach (var material in GetComponent<Renderer>().materials) { Destroy(material); } } }
ちなみにResources.UnloadUnusedAssets()
を使うことでも解放されますが、重い処理なので推奨はされていないようです。
MeshFilter.meshも同様
Renderer.material
と同様にMeshFilter.mesh
で取得したメッシュにも注意が必要です。
こちらも同様、自分で破棄しないとリークしてしまいます。
破棄されていることを確認する
マテリアルがきちんと破棄されていることを確認するためにはProfilerを使います。
メモリのProfilerを監視するとメモリに乗っているマテリアルやメッシュの数が見れるので、これらが正常に減っていれば破棄できています。