Dissolv는 머터리얼로 구현을 하며. 점점 사라지는 이벤트를 구현할 때 종종 쓴다.
투명화라던지, 몬스터가 쓰러지고 사라지는 효과라던지. 사용처는 무궁무진하다.
Tip : 해당 이벤트에서는 몬스터가 사라지는 부분은 투명하게 하기 떄문에 블랜드 모드를 Masked로 설정한다. 해당 모드를 어떻게 설정하느냐에 따라 이벤트가 바뀌니 취향에 맞게 설정.
[Monster.h]
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "../GameInfo.h"
#include "GameFramework/Character.h"
#include "Monster.generated.h"
struct FConvertMaterial
{
int32 Index;
UMaterialInstanceDynamic* Mtrl;
FConvertMaterial() :
Index(-1),
Mtrl(nullptr)
{
}
};
UCLASS()
class UE11_API AMonster : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AMonster();
protected:
class UMonsterAnimInstance* mAnimInst;
AActor* mHitActor;
TArray<UMaterialInstanceDynamic*> mDissolvMtrlArray;
TArray<FConvertMaterial> mDissolveMtrlIndexArray;
bool mDissolveEnable;
float mDissolve;
float mDissolveRange;
float mDissolveTime;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = true))
float mDissolveTimeMax;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = true))
float mDissolveMin;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = true))
float mDissolveMax;
public:
void OnDissolve();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser);
[Monster.cpp]
// Fill out your copyright notice in the Description page of Project Settings.
#include "Monster.h"
#include "MonsterAnimInstance.h"
#include "MonsterSpawnPoint.h"
#include "../UE11GameInstance.h"
#include "MonsterAIController.h"
// Sets default values
AMonster::AMonster()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
mDissolveEnable = false;
mDissolveMax = 1.5f;
mDissolveMin = -1.f;
mDissolveTimeMax = 3.f;
mDissolveTime = 0.f;
mDissolve = 0.f;
mDissolveRange = mDissolveMax - mDissolveMin;
}
void AMonster::OnDissolve()
{
if (mDissolvMtrlArray.IsEmpty())
return;
mDissolveEnable = true;
int32 Count = mDissolvMtrlArray.Num();
for (int32 i = 0; i < Count; ++i)
{
mDissolvMtrlArray[i]->SetScalarParameterValue(TEXT("DissolveEnable"), 1.f);
}
}
// Called when the game starts or when spawned
void AMonster::BeginPlay()
{
Super::BeginPlay();
int32 IndexCount = mDissolveMtrlIndexArray.Num();
for (int32 i = 0; i < IndexCount; ++i)
{
UMaterialInstanceDynamic* Mtrl =
GetMesh()->CreateDynamicMaterialInstance(mDissolveMtrlIndexArray[i].Index,
mDissolveMtrlIndexArray[i].Mtrl);
mDissolvMtrlArray.Add(Mtrl);
}
}
mAnimInst = Cast<UMonsterAnimInstance>(GetMesh()->GetAnimInstance());
}
// Called every frame
void AMonster::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (mDissolveEnable)
{
mDissolveTime += DeltaTime;
float Ratio = mDissolveTime / mDissolveTimeMax;
mDissolve = mDissolveMax - Ratio * mDissolveRange;
int32 Count = mDissolvMtrlArray.Num();
for (int32 i = 0; i < Count; ++i)
{
mDissolvMtrlArray[i]->SetScalarParameterValue(TEXT("Dissolve"), mDissolve);
}
if (mDissolveTime >= mDissolveTimeMax)
{
mSpawnPoint->RemoveMonster(this);
Destroy();
}
}
}
[MonsterAnimationInstance.cpp]
void UMonsterAnimInstance::AnimNotify_DeathEnd()
{
AMonster* Monster = Cast<AMonster>(TryGetPawnOwner());
if (IsValid(Monster))
Monster->OnDissolve();
}
[MonsterWarrior.cpp]
AMinionWarrior::AMinionWarrior()
{
FConvertMaterial Mtrl;
Mtrl.Index = 0;
mDissolveMtrlIndexArray.Add(Mtrl);
}