Condividi tramite


Istanza materiale - MRTK2

L'aide MaterialInstance di comportamento nella durata del materiale dell'istanza di rilevamento e distrugge automaticamente i materiali di istanza per l'utente. Questo componente di utilità può essere usato come sostituzione di Renderer.material o Renderer.material.

Nota

MaterialPropertyBlocks è preferibile rispetto al materiale instancing, ma non sempre disponibile in tutti gli scenari.

Perché usare Renderer.material è un problema? Se si aggiunge il codice seguente a una scena unity e l'utilizzo della memoria di hit play continuerà a salire e salire:

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

Il comportamento della perdita precedente si arresterà in modo anomalo su Unity se è stato eseguito troppo a lungo!

In alternativa, provare a usare il 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);
    }
}

Utilizzo

Quando si richiama renderer.material di Unity, Unity crea automaticamente un'istanza di nuovi materiali. È responsabilità del chiamante distruggere i materiali quando un materiale non è più necessario o l'oggetto del gioco viene distrutto. Il MaterialInstance comportamento consente di evitare perdite di materiale e mantenere coerenti i percorsi di allocazione materiale durante la modifica e l'esecuzione.

Quando non è possibile usare materialPropertyBlock e un materiale deve essere usato, MaterialInstance può essere usato come indicato di seguito:

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 più oggetti richiedono la proprietà dell'istanza del materiale, è consigliabile accettare la proprietà esplicita per il rilevamento dei riferimenti. Un'interfaccia facoltativa denominata IMaterialInstanceOwner esiste per aiutare con la proprietà. Di seguito è riportato un esempio di utilizzo:

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.
        ...
    }
}

Per altre informazioni, vedere l'utilizzo dell'esempio illustrato all'interno del ClippingPrimitive comportamento.

Vedi anche