캐릭터가 적이 공격하는 정확한 타이밍에 회피를 실행하여 회피를 하게 되면 캐릭터를 제외한 모든 것이 시간이 멈춘 것처럼 멈추게 되어 적이 무방비상태가 되는 스킬을 구현해봤습니다.
월드의 시간이 멈춘것처럼 구현하는 것은 GlobalTimeDilation의 값을 조절하여 구현했습니다.
캐릭터가 회피 애니메이션을 재생하면 AnimNotifyState 클래스로 적의 공격을 탐지하는 캐릭터 클래스의 ExtremeDodgeArea Collision을 활성화합니다. 회피하는 동안 캐릭터는 적의 공격의 대미지를 받지 않는 상태이며 적의 공격이 캐릭터에게 닿을 경우 SkillSystem의 ExtremeDodge 스킬을 실행합니다.
ExtremeDodge 스킬이 실행되면 캐릭터의 ActivateTimeStop함수를 실행하며 캐릭터와 이펙트 및 오브젝트를 제외한 모든 것이 흑백이 되며 시간이 멈춘것처럼 멈추게 됩니다.
ExtremeDodge는 재사용 대기 시간이거나 정확한 타이밍에 회피하지 못하면 실행되지 않습니다.
void UPRTimeStopSystemComponent::ActivateTimeStop(float NewTimeStopDuration)
{
if(IsValid(GetPROwner()) == true)
{
TimeStopDuration = NewTimeStopDuration;
TimeStopRemaining = TimeStopDuration;
TimeStopElapsed = 0.0f;
bActivate = true;
// 카메라의 모션블러를 설정합니다.
APRPlayerCharacter* PRPlayerCharacter = Cast<APRPlayerCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
if(PRPlayerCharacter != nullptr)
{
ChangeMotionBlurAmount(PRPlayerCharacter->GetFollowCamera()->PostProcessSettings, TimeStopDilation * BaseMotionBlurIntensity);
}
UGameplayStatics::SetGlobalTimeDilation(GetWorld(), TimeStopDilation);
float NewOwnerTimeDilation = OwnerTimeDilation / TimeStopDilation;
FTimerHandle TimerHandle;
FTimerDelegate TimerDelegate = FTimerDelegate::CreateUObject(this, &UPRTimeStopSystemComponent::SetOwnerCustomTimeDilation, NewOwnerTimeDilation);
// Delay를 두고 Owner의 TimeDilation을 설정하지 않으면 Owner가 순간적으로 가속하게 됩니다.
// Delay함수와 달리 타이머는 글로벌 시간 흐름 속도(Global Time Dilation)의 영향을 받습니다.
// 이미 앞선 코드로 인해 클로벌 시간 흐름 속도가 줄어들었으므로 Delay시간을 배로 설정합니다.
GetWorld()->GetTimerManager().SetTimer(TimerHandle, TimerDelegate, TimeStopDilation * TimeStopDilation, false);
if(OnActivateTimeStop.IsBound() == true)
{
OnActivateTimeStop.Broadcast();
}
}
}
void APRPlayerCharacter::ActivateTimeStop(float TimeStopDuration)
{
ActivateMonochromeMode(EPRCameraPostProcessMaterial::CameraPostProcessMaterial_TimeStop, true, false);
GetEffectSystem()->SetActivateTimeStop(true);
GetObjectPoolSystem()->SetActivateTimeStop(true);
GetTimeStopSystem()->ActivateTimeStop(TimeStopDuration);
}
화면을 흑백으로 나타내는 방법으로 PostProcessMaterial를 사용했습니다. TimeStop을 실행하면 플레이어가 사용하는 카메라의 PostProcessMaterial의 배열에 추가한 Material의 값을 조절합니다. 이렇게 PostProcessMaterial의 값을 조절하면 화면 전체가 흑백으로 표현됩니다.
화면 전체가 흑백으로 표현되었기 때문에 플레이어의 캐릭터와 적 캐릭터의 Mesh에서 Custom Depth Stencil Value를 조절하여 흑백표현에서 제외시킵니다.
void APRPlayerCharacter::ActivateMonochromeMode(EPRCameraPostProcessMaterial CameraPostProcessMaterial, bool bUseLerp, bool bReverse)
{
MonochromeMode = CameraPostProcessMaterial;
// 선형보간을 사용하며 선형보간에 필요한 Curve가 존재할 떄
if(bUseLerp && MonochromeFloatCurve != nullptr)
{
if(bReverse)
{
MonochromeModeTimeline.ReverseFromEnd();
}
else
{
MonochromeModeTimeline.PlayFromStart();
}
}
// 선형보간을 사용하지 않거나 선형보간에 필요한 Curve가 존재하지 않을 때
else
{
if(bReverse)
{
SetPostProcessMaterialWeight(CameraPostProcessMaterial, 0.0f);
}
else
{
SetPostProcessMaterialWeight(CameraPostProcessMaterial, 1.0f);
}
}
}
void APRPlayerCharacter::SetPostProcessMaterialWeight(EPRCameraPostProcessMaterial CameraPostProcessMaterial, float Value)
{
if(GetFollowCamera() != nullptr)
{
int32 MaterialIndex = static_cast<int32>(CameraPostProcessMaterial);
FPostProcessSettings NewPostProcessSettings = GetFollowCamera()->PostProcessSettings;
// 설정할 PostProcessMaterial이 존재할 경우
if(NewPostProcessSettings.WeightedBlendables.Array.IsValidIndex(MaterialIndex) == true)
{
NewPostProcessSettings.WeightedBlendables.Array[MaterialIndex].Weight = Value;
// 변경된 설정을 적용합니다.
GetFollowCamera()->PostProcessSettings = NewPostProcessSettings;
}
}
}
PostProcessMaterial로 흑백을 표현할 때 Effect도 같이 흑백으로 표현되므로 ProstProcessMaterial의 Blendable Location을 Befor Translucency로 설정합니다.
'Project > Replica' 카테고리의 다른 글
[Project Replica] Vaulting / Vault / 장애물 뛰어넘기 (0) | 2024.04.15 |
---|---|
[Project Replica] DamageSystem 대미지 시스템 (0) | 2024.01.11 |
[Project Replica] AI 생성 시스템 AISpawnSystem (1) | 2023.12.04 |
[Project Replica] 범위 피해 스킬 Judgement Cut (0) | 2023.10.18 |
[Project Replica] 검기 스킬 Slash Projectile Skill (1) | 2023.10.16 |