Instance de matériau — MRTK2

Le comportement MaterialInstance facilite le suivi de la durée de vie des matériaux d’instance et détruit automatiquement les matériaux instanciés pour l’utilisateur. Ce composant utilitaire peut être utilisé à la place de Renderer.material ou Renderer.materials.

Notes

Les MaterialPropertyBlocks sont préférables à l’instanciation de matériaux mais ne sont pas toujours disponibles dans tous les scénarios.

Pourquoi l’utilisation de Renderer.material peut-elle constituer un problème ? Si vous ajoutez le code ci-dessous à une scène Unity et appuyez sur jouer, l’utilisation de la mémoire continuera à grimper :

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

Notes

Le comportement de Fuite ci-dessus bloquera Unity s’il est exécuté trop longtemps.

En guise d’alternative, essayez d’utiliser le comportement 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);
    }
}

Utilisation

Lors de l’appel de renderer.material(s) d’Unity, Unity instancie automatiquement de nouveaux matériaux. Il incombe à l’appelant de détruire les matériaux quand ils ne sont plus nécessaires ou quand l’objet de jeu est détruit. Le comportement MaterialInstance aide à éviter les fuites de matériaux et à maintenir la cohérence des chemins d’allocation de matériaux pendant la modification et l’exécution.

Quand un MaterialPropertyBlock ne peut pas être utilisé et qu’un matériau doit être instancié, le comportement MaterialInstance peut être utilisé comme suit :

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

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

Si plusieurs objets ont besoin de la propriété de l’instance de matériau, il est préférable de prendre la propriété explicite pour le suivi de référence. (Il existe une interface facultative appelée IMaterialInstanceOwner pour aider à la propriété.) Voici un exemple d’utilisation :

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

Pour plus d’informations, consultez l’exemple d’utilisation présenté dans le comportement ClippingPrimitive.

Voir aussi