Общие сведения об экземпляре материала — MRTK3
Поведение MaterialInstance
помогает отслеживать время существования материала экземпляра и автоматически уничтожает экземплярные материалы для пользователя. Этот компонент служебной программы можно использовать в качестве замены Renderer.material или Renderer.materials.
Примечание
MaterialPropertyBlocks предпочтительнее для создания экземпляров материалов, но не всегда доступны во всех сценариях.
Почему использование 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
.