Descrição geral da instância material – MRTK3
O MaterialInstance
comportamento ajuda a controlar a duração material da instância e destrói automaticamente os materiais instânciados para o utilizador. Este componente utilitário pode ser utilizado como substituição para Renderer.material ou Renderer.materials.
Nota
MaterialPropertyBlocks são preferenciais em vez de 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 a utilização da memória de reprodução continuarão 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 chamador destruir os materiais quando um material já não é necessário ou o objeto do jogo é destruído. O MaterialInstance
comportamento ajuda a evitar fugas de material e mantém os caminhos de alocação material 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 assumir a propriedade explícita para o controlo de referência. (Existe uma interface opcional chamada IMaterialInstanceOwner
para ajudar na propriedade.) Segue-se um exemplo de utilização:
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 o exemplo de utilização demonstrado no ClippingPrimitive
comportamento.