Share via


Instancia de material: MRTK2

El comportamiento MaterialInstance le permite realizar un seguimiento de la duración del material de la instancia y destruye automáticamente los materiales con instancias para el usuario. Este componente de utilidad se puede usar como reemplazo de Renderer.material o Renderer.materials.

Nota

MaterialPropertyBlocks son preferibles a la creación de instancias de material, pero no siempre están disponibles en todos los escenarios.

¿Por qué usar Renderer.material puede ser un problema? Si agrega el código siguiente a una escena de Unity y presiona reproducir, el uso de la memoria seguirá subiendo y subiendo:

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 fuga anterior bloqueará Unity si se ejecutó durante demasiado tiempo

Como alternativa, intente usar el comportamiento 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);
    }
}

Uso

Al invocar Renderer.material(s) de Unity, Unity crea automáticamente instancias de nuevos materiales. Es responsabilidad del autor de la llamada destruir los materiales cuando ya no se necesiten, o se arruina el objeto del juego. El comportamiento MaterialInstance ayuda a evitar fugas de material y mantiene las rutas de asignación de materiales coherentes durante la edición y el tiempo de ejecución.

Cuando no se puede usar MaterialPropertyBlock y tiene que crear una instancia de material, MaterialInstance se puede usar de la siguiente manera:

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 la propiedad explícita para el seguimiento de referencias. (Existe una interfaz opcional denominada IMaterialInstanceOwner que existe para usarla con la propiedad). A continuación se muestra un ejemplo de uso:

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 obtener más información, consulte el ejemplo de uso que se muestra en el ClippingPrimitive comportamiento.

Vea también