오늘 작성할 내용은 다이나믹 머티리얼 인스턴스다.
내용은 간단하다.
머티리얼의 그래프 내 몇몇 노드를 Parameter(매개변수)화 하고, 해당 머티리얼로 인스턴스로 만들면 매개변수를 조작할 수 있다.
매개변수는 Texture가 될 수도, 단순한 float이 될 수도 있다.
그렇게 만들어진 머티리얼 인스턴스는, 같은 머티리얼이지만 전혀 다른 모습이 될 수 있다.
Texture 자체를 바꿔 보이는 모습을 바꾸거나 BaseColor의 색깔을 바꾸기도 하고, Emissive Color 수치를 바꿔 발광하는 수치를 다르게 할 수도 있다.
하지만 머티리얼 인스턴스의 모습은 컴파일 타임에 결정된다.
만약 Emissive Color의 수치를 0에서 100으로 바꾸고 싶다면?
값이 0과 100인 머티리얼 인스턴스 2개를 만들어 갈아끼워야 할까?
그럼 0에서 100까지 천천히 상승하는 모습을 구현하고 싶을 땐?
0에서 100까지 100개의 머티리얼 인스턴스를 만들고 갈아끼워야 할까?
미친 짓이다.
다이나믹 머티리얼 인스턴스를 만들면 된다.
(머티리얼을 만든 과정은 생략)

왼쪽은 머티리얼, 오른쪽은 그 머티리얼을 부모로 하는 머티리얼 인스턴스다.

머티리얼 인스턴스의 매개변수들이다.
다이나믹 머티리얼 인스턴스는 머티리얼 인스턴스를 통해 만든다.
// 아래 머티리얼 인스턴스를 통해 만들어지는 런타임 중 편집 가능한 다이나믹 머티리얼 인스턴스
UPROPERTY(VisibleAnywhere, Category = "Elim")
UMaterialInstanceDynamic* DynamicDissolveMaterialInstance;
// 머티리얼 인스턴스
UPROPERTY(EditAnywhere, Category = "Elim")
UMaterialInstance* DissolveMaterialInstance;
Character의 멤버 변수로 둘을 선언해준다.
머티리얼 인스턴스는 직접 할당해줄 거기 때문에 EditAnywhere, 다이나믹 머티리얼 인스턴스는 런타임 중 생성되기 때문에 Edit까진 필요하지 않다.
// MulticastElim 함수 중 일부
if (DissolveMaterialInstance)
{
// 다이나믹 머티리얼 인스턴스 생성
DynamicDissolveMaterialInstance = UMaterialInstanceDynamic::Create(DissolveMaterialInstance, this);
// 메쉬에 다이나믹 머티리얼 인스턴스 할당
GetMesh()->SetMaterial(0, DynamicDissolveMaterialInstance);
// 매개변수 초기값 세팅
DynamicDissolveMaterialInstance->SetScalarParameterValue(TEXT("Dissolve"), 0.55f);
DynamicDissolveMaterialInstance->SetScalarParameterValue(TEXT("Glow"), 200.f);
}
StartDissolve();
// 다이나믹 머티리얼 인스턴스 매개변수 조작 시작
void ABlasterCharacter::StartDissolve()
{
// 시간에 따라 DissolveCurve대로 변화하는 값을 매개변수로 DissolveTrack에 바인딩된 함수를 프레임마다 호출
DissolveTrack.BindDynamic(this, &ThisClass::UpdateDissolveMaterial);
if (DissolveCurve && DissolveTimeline)
{
// 타임라인 컴포넌트에 DissolveCurve와 DissolveTrack을 등록
DissolveTimeline->AddInterpFloat(DissolveCurve, DissolveTrack);
// 타임라인 시작
DissolveTimeline->Play();
}
}
void ABlasterCharacter::UpdateDissolveMaterial(float DissolveValue)
{
if (DynamicDissolveMaterialInstance)
{
DynamicDissolveMaterialInstance->SetScalarParameterValue("Dissolve", DissolveValue);
}
}
타임라인 컴포넌트와 델리게이트 FOnTimelineFloat을 선언, UCurveFloat도 선언해 블루프린트에서 할당했다.
타임라인이 시작되면 등록된 커브대로 변화하는 float값을 델리게이트에 등록된 함수에 매개변수로 넣어 호출한다.
그러니까 매 프레임 변화하는 float을 매개변수로 UpdateDissolveMaterial이 호출된다는 뜻이다.
결과는 프레임마다 DynamicDissolveMaterialInstance의 Dissolve라는 이름의 변수에 DissolveValue가 할당된다.
커브는 0.5에서 -0.5로 변화하도록 만들어놨다.

적용될 다이나믹 머티리얼 인스턴스의 모습이다. 값이 변화하면서 이렇게 된다.

결과물이다.
로봇은 그냥 이미터 스폰이라 게시글까지 쓰는 건 생략했다.
사망 시 Collision도 조작해 더이상 총알에 맞지 않게 했으며, 크로스헤어가 빨갛게 변하지도 않도록 했다.
그 외에 PlayerStart를 이용한 랜덤 위치 리스폰도 제작했다.
결과물이 하나씩 쌓이면서 점점 게임 구색을 갖춰가는 게 너무 즐겁다.