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.