![[Unreal Engine C++] Dash의 기능에서 개선된 Dodge의 구현](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm7UKv%2FbtsI9PIoUFo%2FXC7Mqc3OisowSk5UBgMsik%2Fimg.png)
개요
[Unreal Engine C++] Dash 구현
캐릭터의 Dash를 구현할 때, Launch Character를 사용하여 구현하면 간단하지만 공중으로 Dash할 때와 지면에서 Dash할 때의 이동 거리가 다르다는 문제점이 발생하였다. 이는 지면에 있을 때엔 지면 마
zeniff.tistory.com
이 글에서 구현했던 Dash 방식은 캐릭터의 순간 속도를 빠르게 만든 뒤, AddMovementInput으로 한칸 이동하는 방식을 사용하였다.
이 방식은 필자의 기준에 당시엔 괜찮았지만 지금 보면 생각했던 대쉬라는 기능에 대해 좀 아쉬운 방식이다.
많은 사람들이 Dash에 대해 생각할 때엔 속도가 빨라져서 뛰는 느낌일수도 있지만 순간이동 또는 피하는 회피 기술을 떠올릴 수도 있다고 생각한다.
이를 필자는 Dodge 라는 명칭으로 부를 것이고, Dash에 사용하였던 구현 방식을 개선해보자.
언리얼 에디터에서 준비
필자는 Unreal 5.4버전을 사용중이므로 그 버전에 맞게 구현해보겠다.
이전 글과 같이 기타 - 커브를 이용해 커브를 만들어줄 것이다.
일직선으로 되어 있는 줄에 우클릭 - 키 값 추가로 값을 두개 추가할 것이다.
각각의 값은 (시간, 강도) 기준으로 (0, 0), (0.25, 1)의 기준으로 맞춰주었다. 시간은 원하는 Dodge시간으로 적어주면 된다.
기본적으로 구현되어 있는 ThirdPerson을 사용할 것이기 때문에 Content/ThirdPerson/Input/Actions에 가서 입력 액션을 하나 만들어준다. 필자는 IA_Dodge라는 이름으로 만들었다.
연속으로 눌러서 사용하는 것이 아닌 한번 누르면 작동되는 형식이므로, 값 타임은 bool값으로 설정한다.
Content/ThirdPerson/Input 에 보면 기본적으로 IMC_Default라고 액션 매핑을 위한 데이터 에셋이 존재한다.
이는 캐릭터의 입력 액션을 설정해주는 에셋이므로 이 파일에 추가한 Dodge 키 값을 알려주자.
매핑을 눌러 Dodge를 추가해주고, 트리거는 눌림으로 설정해주면 모든 준비는 끝났다.
C++에서의 구현
기본적으로 구현되어 있는 Character파일에서 수행할 것이다.
// Character.h
UCLASS(config=Game)
class AUdemyProjectCharacter : public ACharacter
{
GENERATED_BODY()
...
/** Dash Input Action */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
class UInputAction* DodgeAction;
public:
AUdemyProjectCharacter();
protected:
...
/** Called for dodging input */
void DodgeCheck(const FInputActionValue& Value);
//UFUNCTION(BlueprintImplementableEvent)
void Dodge(const FVector DodgeDir, const FVector DodgeVel);
...
private:
UPROPERTY(EditAnywhere, Category = "Dodge Option", meta = (AllowPrivateAccess = "true"))
float DodgeDistance;
UPROPERTY()
class UTimelineComponent* DodgeTimeline;
UPROPERTY()
UCurveFloat* DodgeCurve;
UFUNCTION()
void DodgeInterpReturn(float value);
FVector DodgeDirection;
FVector DodgeVelocity;
};
헤더파일에서 함수와 변수값을 지정해준다.
각각에 대한 설명은 다음과 같다.
- class UInputAction* DodgeAction : 언리얼 상에서 만들어 주었던 Dodge 액션을 매핑.
- void DodgeCheck(const FInputActionValue& Value) : 순간이동이 되어 도착하는 위치로 이동할 수 있는지 확인하는 함수.
- void Dodge(const FVector DashDir, const FVector DashVel) : Dodge기능 수행.
- float DodgeDistance : Dodge 거리 설정.
- UTimelineComponent* DodgeTimeline : Dodge를 수행할 타임라인.
- UCurveFloat* DodgeCurve : 타임라인에 사용할 Curve.
- void DodgeInterpReturn(float value) : 타임라인에 있는 Curve가 수행되면서 실행될 함수.
- FVector DodgeDirection : Dodge를 수행하는 방향.
- FVector DodgeVelocity : Dodge를 수행할 때의 속도.
// Character.cpp
#include "Components/TimelineComponent.h"
AUdemyProjectCharacter::AUdemyProjectCharacter()
{
...
static ConstructorHelpers::FObjectFinder<UInputAction> DodgeInput = TEXT("/Script/EnhancedInput.InputAction'/Game/ThirdPerson/Input/Actions/IA_Dodge.IA_Dodge'");
if (DodgeInput.Object) {
DodgeAction = DodgeInput.Object;
}
const ConstructorHelpers::FObjectFinder<UCurveFloat> Curve(TEXT("/Script/Engine.CurveFloat'/Game/Udemy/Character/Dodge/CV_Dodge.CV_Dodge'"));
if (Curve.Succeeded()) {
DodgeCurve = Curve.Object;
}
DodgeTimeline = CreateDefaultSubobject<UTimelineComponent>(TEXT("DodgeTimeline"));
DodgeDistance = 500.0f;
DodgeDirection = FVector::ZeroVector;
DodgeVelocity = FVector::ZeroVector;
}
생성자에서 기본 값들을 설정해준다.
// Character.cpp
void AUdemyProjectCharacter::BeginPlay()
{
// Call the base class
Super::BeginPlay();
FOnTimelineFloat DodgeCallback;
DodgeCallback.BindUFunction(this, FName("DodgeInterpReturn"));
DodgeTimeline->SetLooping(false);
DodgeTimeline->AddInterpFloat(DodgeCurve, DodgeCallback);
DodgeTimeline->SetTimelineLength(0.25f);
}
시작하는 BeginPlay()에서 타임라인을 설정해준다.
Dodge가 수행될 때 CallBack 되는 함수를 지정해주고(DodgeInterpReturn) 반복여부는 false, DodgeCurve에 따라 수행되면서 CallBack이 수행될 수 있게 설정, 타임라인 시간을 0.25초로 지정해준다.
// Character.cpp
void AUdemyProjectCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
...
// Set up action bindings
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
...
//Dodging
EnhancedInputComponent->BindAction(DodgeAction, ETriggerEvent::Triggered, this, &AUdemyProjectCharacter::DodgeCheck);
}
...
}
Dodge버튼이 눌렸을 때 DodgeCheck함수가 실행 되도록 바인드 해준다.
이제 Dodge키를 누르게 되면 DodgeCheck가 실행되는데 이 때 순간이동이 완료되는 위치로 이동 할 수 있는지 확인할 것이다.
// Character.cpp
void AUdemyProjectCharacter::DodgeCheck(const FInputActionValue& Value)
{
// If input vector not equal ZeroVector
if (GetCharacterMovement()->GetLastInputVector() != FVector::ZeroVector) {
FHitResult HitResult;
bool IsHit = GetWorld()->LineTraceSingleByChannel(HitResult,
GetActorLocation(),
GetActorLocation() + (GetCharacterMovement()->GetLastInputVector() * DodgeDistance),
ECollisionChannel::ECC_Visibility);
if (IsHit)
Dodge(HitResult.Location + (GetCharacterMovement()->GetLastInputVector() * -55.0f), GetActorForwardVector());
else
Dodge(GetActorLocation() + (GetCharacterMovement()->GetLastInputVector() * DodgeDistance), GetActorForwardVector());
}
}
마지막 입력이 ZeroVector, 즉 중립이 아니면 실행이 되는데, LineTrace를 이용하여 현재 액터의 위치와 마지막 입력이 가해졌던 방향에 DodgeDistance를 곱해 나온 위치로 쏠 것이다.
이 때 액터 또는 무언가 존재하여 IsHit값이 True가 주어진다면 맞은 액터의 위치값에 캐릭터의 몸 값을 빼서 이동을 진행하고, 없다면 DodgeDistance만큼 이동하도록 설정한다.
// Character.cpp
void AUdemyProjectCharacter::Dodge(const FVector DodgeDir, const FVector DodgeVel)
{
DodgeDirection = DashDir;
DodgeVelocity = DashVel;
DodgeTimeline->PlayFromStart();
}
void AUdemyProjectCharacter::DodgeInterpReturn(float value)
{
SetActorLocation(FMath::Lerp(GetActorLocation(), DodgeDirection, value));
}
Dodge가 수행될 때 Direction과 Velocity값을 받아온 값으로 지정해주고, Timeline을 수행한다.
타임라인이 수행될 때엔 SetActorLocation(FMath::Lerp(GetActorLocation(), DodgeDirection, value)) 가 수행되면서 점진적으로 로케이션이 이동될 것이다.
결과
원하는 느낌으로 구현이 되었다.
'UnrealEngine > 공부' 카테고리의 다른 글
[Unreal Engine C++] 액터를 원 안의 랜덤 위치에 스폰시키기 (1) | 2024.11.25 |
---|---|
[Unreal Engine BP] 캐릭터 카메라를 액터에 Close Up 하기 (0) | 2024.09.28 |
[Unreal Engine C++] Widget Blueprint를 이용해 세션 생성 및 접속 기능 만들기 (0) | 2024.08.15 |
[GitLab] SourceTree를 활용해 팀 프로젝트 진행해보기 (0) | 2024.08.04 |
[Unreal Engine C++] C++에서 Niagara System 스폰 (1) | 2024.05.29 |
CSE & GAME 개발 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 부탁드립니다!