Instância material — MRTK2

Os MaterialInstance auxiliares de comportamento no controlo da duração material da instância e destroem automaticamente os materiais instânciados para o utilizador. Este componente utilitário pode ser utilizado como uma substituição para Renderer.material ou Renderer.materials.

Nota

Os MaterialPropertyBlocks são preferenciais em vez do instancing material, mas nem sempre estão disponíveis em todos os cenários.

Por que motivo a utilização de Renderer.material pode ser um problema? Se adicionar o código abaixo a uma cena do Unity e atingir a utilização da memória de reprodução, continuará a subir e a subir:

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

O comportamento de Fuga acima irá falhar o Unity se for executado durante demasiado tempo!

Como alternativa, tente utilizar o MaterialInstance comportamento:

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

Utilização

Ao invocar renderer.material(s) do Unity, o Unity instancia automaticamente novos materiais. É da responsabilidade do autor da chamada destruir os materiais quando um material já não é necessário ou o objeto de jogo é destruído. O MaterialInstance comportamento ajuda a evitar fugas de material e mantém os caminhos de alocação de materiais consistentes durante o tempo de edição e execução.

Quando um MaterialPropertyBlock não pode ser utilizado e um material tem de ser instânciado, MaterialInstance pode ser utilizado da seguinte forma:

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 material, é melhor tomar a propriedade explícita para o controlo de referência. (Existe uma interface opcional chamada IMaterialInstanceOwner para auxiliar com a propriedade.) Abaixo encontra-se a utilização 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, veja a utilização de exemplo demonstrada no ClippingPrimitive comportamento.

Ver também