Materialinstanz

Das Verhalten spricht für die Nachverfolgung der Lebensdauer von Instanzmaterial und zerstört automatisch MaterialInstance Instanzmaterialien für den Benutzer. Diese Hilfsprogrammkomponente kann als Ersatz für Renderer.material oder Renderer.materials verwendet werden.

Hinweis

MaterialPropertyBlocks werden der Materialinstancierung vorgezogen, sind aber nicht immer in allen Szenarien verfügbar.

Warum kann die Verwendung von Renderer.material ein Problem sein? Wenn Sie den folgenden Code zu einer Unity-Szene hinzufügen und die Speicherauslastung für Trefferplays weiterhin tosen und totschlagen wird:

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 genannte Leak-Verhalten stürzt Unity ab, wenn es zu lange läuft!

Alternativ können Sie versuchen, das Verhalten MaterialInstance 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);
    }
}

Verbrauch

Beim Aufrufen von Renderer.material(s) von Unity instanziiert Unity automatisch neue Materialien. Es liegt in der Verantwortung des Aufrufers, die Materialien zu zerstören, wenn ein Material nicht mehr benötigt wird oder das Spielobjekt zerstört wird. Das MaterialInstance Verhalten hilft dabei, Materiallecks zu vermeiden und die Materialzuordnungspfade während der Bearbeitung und Laufzeit konsistent zu halten.

Wenn ein MaterialPropertyBlock nicht verwendet werden kann und ein Material instanziert werden muss, kann wie MaterialInstance 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, den expliziten Besitz für die Verweisnachverfolgung zu übernehmen. (Zur Unterstützung des IMaterialInstanceOwner Besitzes ist eine optionale Schnittstelle namens vorhanden.) Im Folgenden finden Sie ein Beispiel für die Verwendung:

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 Beispielverwendung, die innerhalb des Verhaltens demonstriert ClippingPrimitive wird.

Siehe auch