Übersicht zur Materialinstanz — MRTK3

Das MaterialInstance-Verhalten ist beim Nachverfolgen der Lebensdauer von Instanzmaterialien behilflich und zerstört instanziierte Materialien automatisch für den Benutzer. Diese Hilfskomponente kann als Ersatz für Renderer.material oder Renderer.materials verwendet werden.

Hinweis

MaterialPropertyBlocks werden gegenüber Materialinstanzen bevorzugt, sind aber nicht immer in allen Szenarien verfügbar.

Warum kann die Verwendung von Renderer.material ein Problem darstellen? Wenn Sie einer Unity-Szene den folgenden Code hinzufügen und die Wiedergabe aktivieren, steigt die Speicherauslastung fortlaufend immer weiter an:

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);
    }
}

Hinweis

Das oben erwähnte Leak-Verhalten führt zu einem Absturz von Unity, wenn es zu lange ausgeführt wird!

Versuchen Sie alternativ, das MaterialInstance-Verhalten zu verwenden:

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);
    }
}

Verwendung

Beim Aufrufen der Renderer.material(s) von Unity instanziiert Unity automatisch neue Materialien. Es liegt in der Zuständigkeit des Anrufers, die Materialien zu zerstören, wenn ein Material nicht mehr benötigt oder das Spielobjekt zerstört wird. Das MaterialInstance-Verhalten hilft, Materiallecks zu vermeiden und hält Materialzuweisungspfade in der Bearbeitung und zur Laufzeit konsistent.

Wenn ein MaterialPropertyBlock nicht verwendet werden kann und ein Material instanziiert werden muss, kann MaterialInstance wie folgt verwendet werden:

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

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

Wenn mehrere Objekte den Besitz der Materialinstanz benötigen, ist es am besten, expliziten Besitz für die Referenzverfolgung zu übernehmen. (Es ist eine optionale Schnittstelle IMaterialInstanceOwner vorhanden, um die Besitzübernahme zu erleichtern.) Unten finden Sie ein Verwendungsbeispiel:

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.
        ...
    }
}

Weitere Informationen finden Sie in der Beispielnutzung, die im ClippingPrimitive-Verhalten gezeigt wird.

Weitere Informationen