재질 instance - MRTK2

MaterialInstance 동작은 인스턴스 재질 수명 추적을 보조하고 사용자의 인스턴스 재질을 자동으로 삭제합니다. 이 유틸리티 구성 요소는 Renderer.material 또는 Renderer.materials를 대체하는 용도로 사용할 수 있습니다.

참고

MaterialPropertyBlock은 재질 인스턴스화보다 선호되지만 모든 시나리오에서 항상 사용할 수 있는 것은 아닙니다.

Renderer.material을 사용하는 것이 문제가 될 수 있는 이유는 무엇인가요? Unity 장면에 아래 코드를 추가했는데 적중 재생 메모리 사용량이 계속 상승하는 경우:

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

참고

너무 오래 실행하면 위의 누수 동작이 Unity와 충돌합니다.

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

사용량

Unity의 Renderer.material을 호출하면 Unity가 자동으로 새 재질을 인스턴스화합니다. 재질이 더 이상 필요하지 않거나 게임 개체가 제거될 때 재질을 삭제하는 것은 호출자의 책임입니다. MaterialInstance 동작은 재질 누수를 방지하고 편집 및 실행 시간 동안 재질 할당 경로를 일관되게 유지하는 데 도움이 됩니다.

MaterialPropertyBlock을 사용할 수 없으며 재질을 인스턴스화해야 하는 경우 MaterialInstance를 다음과 같이 사용할 수 있습니다.

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

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

여러 개체에 재질 인스턴스의 소유권이 필요한 경우 참조 추적을 위해 명시적 소유권을 사용하는 것이 가장 좋습니다. (소유권을 보조하기 위해 IMaterialInstanceOwner라는 선택적 인터페이스가 있습니다.) 다음은 사용 예제입니다.

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

자세한 내용은 ClippingPrimitive 동작 내에 설명된 사용 예제를 참조하세요.

참고 항목