次の方法で共有


マテリアル インスタンス — MRTK2

MaterialInstance動作は、インスタンスマテリアルの有効期間の追跡を支援し、ユーザーのインスタンス化されたマテリアルを自動的に破棄します。 このユーティリティ コンポーネントは、 Renderer.material または Renderer.material の代わりに使用できます。

注:

MaterialPropertyBlocks はマテリアルのインスタンス化よりも優先されますが、すべてのシナリオで常に使用できるわけではありません。

Renderer.material の使用が問題になるのはなぜですか? 次のコードをUnityシーンに追加し、再生メモリの使用量をヒットすると、引き続き上昇し、上昇します。

public class Leak : MonoBehaviour
{
    private void Update()
    {
        var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        // Memory leak, the material allocated is not tracked & destroyed.
        cube.GetComponent<Renderer>().material.color = Color.red;
        ...
        Destroy(cube);
    }
}

注:

上記のリーク動作は、実行時間が長すぎるとUnityクラッシュします。

別の方法として、 MaterialInstance 動作を使用してみてください。

public class NoLeak : MonoBehaviour
{
    private void Update()
    {
        var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        // No memory leak, the material allocated is tracked & destroyed by MaterialInstance.
        cube.EnsureComponent<MaterialInstance>().Material.color = Color.red;
        ...
        Destroy(cube);
    }
}

使用方法

Unityの Renderer.material を呼び出すと、Unityは自動的に新しいマテリアルをインスタンス化します。 マテリアルが不要になった場合やゲーム オブジェクトが破棄された場合、マテリアルを破棄するのは呼び出し元の責任です。 MaterialInstance動作は、マテリアル リークを回避し、編集時と実行時にマテリアル割り当てパスの一貫性を維持するのに役立ちます。

MaterialPropertyBlock を使用できない場合、マテリアルをインスタンス化する必要がある場合は、MaterialInstance次のように使用できます。

public class MyBehaviour : MonoBehaviour
{
    // Assigned via the inspector.
    public Renderer targetRenderer;

    private void OnEnable()
    {
        Material material = targetRenderer.EnsureComponent<MaterialInstance>().Material;
        material.color = Color.red;
        ...
    }
}

複数のオブジェクトがマテリアル インスタンスの所有権を必要とする場合は、参照追跡のために明示的な所有権を取得することをお勧めします。 ( IMaterialInstanceOwner と呼ばれる省略可能なインターフェイスは、所有権を持つ側に存在します)。使用例を次に示します。

public class MyBehaviour : MonoBehaviour,  IMaterialInstanceOwner
{
    // Assigned via the inspector.
    public Renderer targetRenderer;

    private void OnEnable()
    {
        Material material = targetRenderer.EnsureComponent<MaterialInstance>().AcquireMaterial(this);
        material.color = Color.red;
        ...
    }

    private void OnDisable()
    {
        targetRenderer.GetComponent<MaterialInstance>()?.ReleaseMaterial(this)
    }

    public void OnMaterialChanged(MaterialInstance materialInstance)
    {
        // Optional method for when materials change outside of the MaterialInstance.
        ...
    }
}

詳細については、 ClippingPrimitive 動作で示されている使用例を参照してください。

関連項目