[Unreal_C++_DarkSoul]#11_Parkour(Vaulting)
장애물을 비교적 수월하게 극복하기 위해 Parkour 동작을 구현합니다.
Unreal 포트폴리오 작업 과정을 기록합니다.
Overview
- 개요
- 설계
- 상세 내용
- 게임 플레이 화면
개요
1. 목적
- Player가 장애물을 보다 자연스럽게 넘어갈 수 있도록 합니다.
- Player가 기본 동작만으로 극복할 수 없는 장애물들을 키 입력 하나로 보다 수월하게 극복할 수 있도록 합니다.
- Player의 게임 플레이 과정에서 찾을 수 있는 재미 요소(?)를 추가하기 위함입니다.
2. 개요
- 먼저, First Person Character를 기준으로 세 가지 Line Tracing을 수행합니다.
- 세 가지 Line Tracing을 통해 장애물과 FPC과의 거리, 장애물의 높이, 마지막으로 장애물의 두께를 측정합니다.
- 각각의 Line Tracing 과정을 통해 FPC가 해당 장애물을 "Parkour" 동작을 통해 극복할 수 있는지 결정합니다.
- 결과적으로, 세 가지 Line Tracing 조건들과 합치하는 장애물을 마주한 FPC는 "Parkour" 동작을 통해 해당 장애물을 극복합니다.
설계
1. Vault Component
- Unreal의 "UActorComponent" 클래스를 상속하는 Vault Component를 생성합니다.
- Player의 Parkour 동작 수행을 정의합니다.
2. VaultComponent::DetectWall()
- DetectWallFront(), DetectWallHeight(), 그리고 DetectWallDepth()를 차례대로 호출합니다.
- 위에서 설명했듯, 위 세 함수는 FPC가 해당 장애물을 "Parkour"를 통해 극복할 수 있는지 가늠하기 위함입니다.
3. Player의 상태 변경
- FPC가 "Parkour" 동작을 수행하는 과정을 화면에 그려내기 위해 "Anim Montage"를 재생합니다.
- FPC가 장애물과 불필요한 "충돌"을 피하기 위해 Capsule Collision의 충돌 여부를 변경해야 합니다.
- FPC가 "Parkour" 과정에서 이외 다른 동작을 수행하지 못하도록, 상태 기계(상태 값) 또한 관리해야 합니다.
- FPC의 "Parkour" 동작을 수행함으로써, 응당 변경해야 하는 "Rotation"과 "Location" 값 또한 변경해야합니다.
상세 내용
1. DetectWall()
bool UC_VaultComponent::DetectWall(class APlayerCharacter** InPlayer)
{
bCanVault = true;
// #1 Player와 Wall과의 거리
bCanVault &= DetectWallFront(InPlayer);
// #2 Wall의 높이
if (bCanVault == true)
bCanVault &= DetectWallHeight(InPlayer);
// #3 Wall의 두께
if (bCanVault == true || bCanClimb == true)
bCanVault &= DetectWallDepth(InPlayer);
return bCanVault || bCanClimb;
}
Details
- 먼저, Player와 Wall(장애물)과의 거리를 계산합니다.
- 위 조건이 합치한다면, DetectWall 함수는 다음으로 장애물의 높이, 그리고 장애물의 두께를 측정합니다.
- 이때, 장애물의 높이 조건을 살펴보는 과정에서 "Vault" 동작으로 극복할 수 없지만, "Climb" 동작으로 극복 가능할 경우를 대비해 "bCanClimb" 변수의 조건 또한 고려합니다.
2. FixRotation() + FixLocation()
void UC_VaultComponent::FixRotation(class APlayerCharacter** InPlayer)
{
FRotator Rotation = (*InPlayer)->GetActorRotation();
FRotator ChangeRotation = FrontWallNormalLocation.Rotation();
ChangeRotation.Yaw += 180.f;
Rotation.Yaw = ChangeRotation.Yaw;
(*InPlayer)->SetActorRotation(Rotation);
}
void UC_VaultComponent::FixLocation(APlayerCharacter** InPlayer, float InFloat1, float InFloat2)
{
FVector ChangeLocation = (UKismetMathLibrary::GetForwardVector(FrontWallNormalLocation.Rotation())) * InFloat1 + FrontWallLocation;
float VectorZ = HeightWallLocation.Z + InFloat2;
FVector NewLocation = FVector(ChangeLocation.X, ChangeLocation.Y, VectorZ);
(*InPlayer)->SetActorLocation(NewLocation);
}
Details
- FixRotation() 함수는 DetectWall() 함수의 결과 값이 "True"라면, Player의 "Rotataion" 값 변환을 정의합니다.
- FixLocation() 함수는 Player가 최종적으로 "Parkour" 동작을 수행하며, 변환될 "Location"값을 정의합니다.
3. OnCollision() + OffCollision()
void UC_VaultComponent::OnCollision()
{
AActor* OwnerActor = GetOwner();
CheckNull(OwnerActor);
APlayerCharacter* OwnerPlayer = Cast<APlayerCharacter>(OwnerActor);
CheckNull(OwnerPlayer);
OwnerPlayer->GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
OwnerPlayer->GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_Walking);
}
void UC_VaultComponent::OffCollision(APlayerCharacter** InPlayer)
{
(*InPlayer)->GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
(*InPlayer)->GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_Flying);
}
Details
- OnCollision() 메서드와 OffCollision() 메서드는 Player와 장애물의 불필요한 "충돌"을 방지하기 위해 Player의 Capusle 컴포넌트의 충돌 여부를 정의합니다.
- 이때, "OnCollision()" 메서드는 Player가 장애물을 온전히 극복하고 호출되는 함수로, "Timer"를 활용합니다.
결과 화면
'개인프로젝트' 카테고리의 다른 글
[Unreal_C++_DarkSoul]#13_기능 구현, Impact Effect (0) | 2023.02.05 |
---|---|
[Unreal_C++_DarkSoul]#12_문제 해결, Targeting 회전 속도 (0) | 2022.12.25 |
[Unreal_C++_DarkSoul]#10_문제 해결, AIController (0) | 2022.12.25 |
[Unreal_C++_DarkSoul]#9_기능 구현, Status Effect 기능 (0) | 2022.12.18 |
[Unreal_C++_DarkSoul]#8_문제 해결, Send Damage 방식 수정 (0) | 2022.12.18 |