Instância de material — MRTK2

O comportamento MaterialInstance auxilia no acompanhamento do tempo de vida do material da instância e destrói automaticamente materiais em instâncias para o usuário. Esse componente do utilitário pode ser usado como uma substituição para Renderer.material ou Renderer.materials.

Observação

MaterialPropertyBlocks são preferenciais em relação à instanciação de material, mas nem sempre estão disponíveis em todos os cenários.

Por que o uso de Renderer.material pode ser um problema? Se você adicionar o código abaixo a uma cena do Unity e apertar executar, o uso da memória continuará subindo:

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

Observação

O comportamento de vazamento acima falhará no Unity se for executado por muito tempo!

Como alternativa, tente usar o comportamento 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

Ao invocar Renderer.material(s) do Unity, o Unity cria automaticamente uma instância de novos materiais. É responsabilidade do chamador destruir os materiais quando um material não é mais necessário ou o objeto do jogo é destruído. O comportamento MaterialInstance ajuda a evitar vazamentos de material e mantém os demarcadores de alocação de material consistentes durante o tempo de edição e execução.

Quando MaterialPropertyBlock não pode ser usado e uma instância de material precisar ser criada, MaterialInstance pode ser usado da seguinte maneira:

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

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

Se vários objetos precisarem de propriedade da instância de material, é melhor tomar a propriedade explícita para o acompanhamento de referência. (Existe uma interface opcional chamada IMaterialInstanceOwner para auxiliar com a propriedade.) Veja abaixo o uso de exemplo:

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 obter mais informações, consulte o uso de exemplo demonstrado no comportamento ClippingPrimitive.

Confira também