현재 만들어져있는 포스트프로세스는 인게임에서 사용하려면 Material Instance로써 들어가야한다.
만든 포스트 프로세스에 우클릭을 하여 Create Material Instnace를 눌러 인스턴스를 만들어, 이름을 PPI_ScreenDamage로 지었다.
그리고 그 인스턴스가 들어갈 곳은 PostProcessVolume의 Post Process Materials 배열 내부이다.
C++ 코드에서 머티리얼 인스턴스를 저기에 집어넣고, 플레이어 체력에 따라 Radius를 조정하는 것까지 수행할 것이다.
KannaCharacter.h에 다음과 같은 변수를 추가하였다.
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = Material)
UMaterialInstance* ScreenDamage;
UPROPERTY()
UMaterialInstanceDynamic* ScreenDamageDynamic;
ScreenDamage에는 PPI_ScreenDamage가 들어갈 것이고, ScreenDamageDynamic은 ScreenDamage를 토대로 만들 다이나믹 인스턴스를 담을 변수이다.
런타임 중 PPI_ScreenDamage의 파라미터인 Radius를 바꿀 것이기 때문에, 그냥 UMaterialInstance가 아닌 UMaterialInstanceDynamic을 사용해야한다.
ScreenDamageDynamic은 BeginPlay에서 생성할 것이다.
// Called when the game starts or when spawned
void AKannaCharacter::BeginPlay()
{
Super::BeginPlay();
if (APlayerController* PlayerController = Cast<APlayerController>(GetController()))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->AddMappingContext(InputMappingContext, 0);
}
}
PunchHitbox->OnComponentBeginOverlap.AddDynamic(this, &AKannaCharacter::OnHitboxOverlap);
KickHitbox->OnComponentBeginOverlap.AddDynamic(this, &AKannaCharacter::OnHitboxOverlap);
IsCameraAtRight = true;
AimingDirection = EAimingDirection::EAD_Neutral;
//위젯 초기화
InitKannaTpsOverlay();
// 화면 데미지 효과 포스트 프로세스 생성, 초기화
ScreenDamageDynamic = UMaterialInstanceDynamic::Create(ScreenDamage, GetWorld());
APostProcessVolume* Volume = Cast<APostProcessVolume>(UGameplayStatics::GetActorOfClass(GetWorld(), APostProcessVolume::StaticClass()));
Volume->Settings.WeightedBlendables.Array.Add(FWeightedBlendable(1.f, ScreenDamageDynamic));
}
마지막 3줄이 해당하는 코드이다.
- ScreenDamage를 토대로 ScreenDamageDynamic을 만들고
- 인게임의 PostProcessVolume 액터에 해당하는 APostProcessVolume을 찾아내고,
- PostProcessMaterials 내 배열에 넣을 수 있는 FWeightedBlendable 구조체를 만들고, 그 구조체를 Settings->WeightedBlendables 내부의 Array에 추가하였다.
FWeightedBlendable을 만들 때 1.f를 넣은 파라미터는 InWeight로, 포스트 프로세스의 영향력을 나타낸다. 따라서 최댓값인 1로 해주었다.
솔직히 배열에 넣는 것을 C++ 코드로 어떻게 처리해야하는지 몰라 상당히 헤맸다.
에디터의 PostProcessMaterials가 C++ 코드에서의 FWeightedBlendables와 같다는 것이 중요하다.
플레이어의 체력에 따라 Radius를 설정해주는 것은 Tick 함수에서 구현하였다.
// Called every frame
void AKannaCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 엄폐중이고, 키보드에서 손을 뗐을 시 캐릭터의 방향 결정
if (IsInCover && (GetVelocity().Length() == 0))
{
if (bIsCrouched)
{
FVector Direction = GetCharacterMovement()->GetPlaneConstraintNormal() * -1.f; //벽면을 바라봄
AddMovementInput(Direction);
}
}
//Radius 설정
float ScreenDamageRadius =
FMath::GetMappedRangeValueClamped(TRange<float>(0.f, 100.f), TRange<float>(0.3f, 1.f), Attributes->GetCurrentHealth());
ScreenDamageDynamic->SetScalarParameterValue(FName("Radius"), ScreenDamageRadius);
}
플레이어의 체력은 0~100까지이고, Radius의 적정값은 0.3~1이다. (0.3 쪽이 화면이 붉고, 1 쪽이 화면이 깨끗해진다.)
따라서 GetMappedRangeValueClamped를 통해 플레이어의 현재 체력을 받은 뒤, 그 값을 손쉽게 0~100 범위에서 0.3~1 범위로 매핑할 수 있었다.
그리고 SetScalarParameterValue 함수를 통해 Radius를 설정해주었다.
테스트 영상:
https://www.youtube.com/watch?v=bnxy2w-6QIc&lc=UgyFxc_DjrvFGXQ0ts94AaABAg&ab_channel=Ciel45
'언리얼 엔진 5 > 개발 일지' 카테고리의 다른 글
[UE5] 블루아카이브 TPS게임 개발일지 (51) - EX 게이지 제작 (0) | 2024.01.28 |
---|---|
[UE5] 블루아카이브 TPS게임 개발일지 (50) - 맵 제작 (2) | 2024.01.28 |
[UE5] 블루아카이브 TPS게임 개발일지 (48) - 스크린 데미지 효과 (Radial Gradient Exponent) (0) | 2024.01.20 |
[UE5] 블루아카이브 TPS게임 개발일지 (47) - HP 자동회복 구현 (0) | 2024.01.20 |
[UE5] 블루아카이브 TPS게임 개발일지 (46) - 피격 방향 표시기 구현 3 (0) | 2024.01.20 |