Как изменить цвет материала на меше во время выполнения в Unreal Engine?
Перекрасьте один меш в рантайме, не затрагивая другие меши с тем же базовым материалом. Создайте динамический инстанс материала один раз в BeginPlay, затем меняйте его цвет в SetHighlightColor.
Ограничения:
- Используйте
UMaterialInstanceDynamicчерезCreateDynamicMaterialInstance— не правьте базовый ассет. - Создайте и закэшируйте инстанс один раз (в
BeginPlay), а не каждый кадр. - Выставляйте именованный векторный параметр (например
"BaseColor"), открытый в материале.
void AHighlightActor::BeginPlay()
{
Super::BeginPlay();
// ваш код здесь
}
void AHighlightActor::SetHighlightColor(const FLinearColor& Color)
{
// ваш код здесь
}
Допишите реализацию.
Создайте UMaterialInstanceDynamic через CreateDynamicMaterialInstance на компоненте, затем вызовите SetVectorParameterValue с именованным параметром. Прямая правка ассета базового материала затронула бы каждый меш с ним.
- ✗Править общий ассет базового материала, что меняет цвет на каждом меше с ним
- ✗Забывать, что материал должен иметь именованный векторный параметр, чтобы вызов сработал
- ✗Создавать новый динамический инстанс каждый кадр вместо кэширования и переиспользования одного
- →Когда создавать динамический инстанс материала — в
BeginPlayили по требованию? - →Чем
SetScalarParameterValueотличается отSetVectorParameterValue?
Задача
Нужно покрасить меш в нужный цвет во время игры — например, подсветить объект при наведении. Базовый материал нельзя править напрямую: он общий, и правка затронет все меши, которые его используют.
Решение
Создаём UMaterialInstanceDynamic (MID) — лёгкий инстанс, который переиспространяет скомпилированный шейдер базового материала и позволяет менять открытые параметры.
// В заголовке актора:
UPROPERTY()
UMaterialInstanceDynamic* DynMaterial = nullptr;
void AHighlightActor::BeginPlay()
{
Super::BeginPlay();
// Создаём MID один раз и кэшируем. Индекс 0 — слот материала на меше.
DynMaterial = MeshComponent->CreateDynamicMaterialInstance(0);
}
void AHighlightActor::SetHighlightColor(const FLinearColor& Color)
{
if (DynMaterial)
{
// "BaseColor" — имя векторного параметра, открытого в графе материала.
DynMaterial->SetVectorParameterValue(TEXT("BaseColor"), Color);
}
}
Ключевые моменты
- В базовом материале параметр должен быть именованным (узел
VectorParameterс именемBaseColor) — иначеSetVectorParameterValueничего не найдёт. CreateDynamicMaterialInstanceвызывается один раз (вBeginPlay), а не каждый кадр — иначе плодятся объекты, нагружающие сборщик мусора.- MID применяется только к этому компоненту; другие меши с тем же базовым материалом не затрагиваются.
- Смена параметра дёшева: перекомпиляции шейдера не происходит — меняется лишь значение в константном буфере.