Instancia de materialMaterial instance

Los asistentes de comportamiento en el seguimiento de la duración del material de la instancia destruyen automáticamente los MaterialInstance materiales de instancia para el usuario.The MaterialInstance behavior aides in tracking instance material lifetime and automatically destroys instanced materials for the user. Este componente de utilidad se puede usar como reemplazo de Renderer.material o Renderer.materials.This utility component can be used as a replacement to Renderer.material or Renderer.materials.

Nota

MaterialPropertyBlocks es preferible a la creación de instancias de material, pero no siempre están disponibles en todos los escenarios.MaterialPropertyBlocks are preferred over material instancing but are not always available in all scenarios.

¿Por qué el uso de Renderer.material puede ser un problema?Why can using Renderer.material be an issue? Si agrega el código siguiente a una escena de Unity y pulsa el uso de memoria de reproducción, el uso de la memoria seguirá siendo desparpase y se verá afectado:If you add the below code to a Unity scene and hit play memory usage will continue to climb and climb:

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

Nota

El comportamiento de pérdida anterior bloqueará Unity si se ejecutó durante demasiado tiempo.The above Leak behavior will crash Unity if ran for too long!

Como alternativa, pruebe a usar el MaterialInstance comportamiento:As an alternative try using the MaterialInstance behavior:

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

UsoUsage

Al invocar el Renderer.material(s) de Unity, Unity crea automáticamente instancias de nuevos materiales.When invoking Unity's Renderer.material(s), Unity automatically instantiates new materials. Es responsabilidad del autor de la llamada destruir los materiales cuando ya no se necesita un material o se destruye el objeto del juego.It is the caller's responsibility to destroy the materials when a material is no longer needed or the game object is destroyed. El MaterialInstance comportamiento ayuda a evitar pérdidas de material y mantiene las rutas de asignación de material coherentes durante el tiempo de edición y ejecución.The MaterialInstance behavior helps avoid material leaks and keeps material allocation paths consistent during edit and run time.

Cuando no se puede usar MaterialPropertyBlock y se debe crear una instancia de un material, MaterialInstance se puede usar de la siguiente manera:When a MaterialPropertyBlock can not be used and a material must be instanced, MaterialInstance can be used as follows:

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

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

Si varios objetos necesitan la propiedad de la instancia de material, es mejor tomar posesión explícita para el seguimiento de referencias.If multiple objects need ownership of the material instance it's best to take explicit ownership for reference tracking. (Existe una interfaz opcional IMaterialInstanceOwner llamada para ayudar con la propiedad). A continuación se muestra un ejemplo de uso:(An optional interface called IMaterialInstanceOwner exists to aide with ownership.) Below is example usage:

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

Para más información, consulte el ejemplo de uso que se muestra dentro del ClippingPrimitive comportamiento.For more information please see the example usage demonstrated within the ClippingPrimitive behavior.

Consulte tambiénSee also