미리보기

구현내용
앞으로 플레이어는 AI와 격돌하게될예정인데
치고받고 싸움을 할때 회피 라는 개념을 넣어서 조금더
역동적인 움직임을 구현하고 싶었습니다
현재 Shift를 누르면 달리기를 실행하는데
Shift를 일정시간 이상 누르면 달리기 짧게 누르면 닷지 를 실행하는 로직으로 구현하였습니다.
구현C++
먼저 Shift를 누르면 누른만큼의 시간을 기록하여 Run인지 Dodge인지 분간할 방법이 필요했습니다
0.18초 동안 감지가 들어오면 달리기 아니면 닷지 로 구분하였습니다
void InputKeyboardShiftPressed();
void InputKeyboardShiftReleased();
bool bShiftPressed = false;
float shiftPressedStartTime = 0.f;
float dodgeThreshold = 0.18f;
float runThreshold = 0.18f;
void AMainCharacterController::InputKeyboardShiftPressed()
{
bShiftPressed = true;
shiftPressedStartTime = GetWorld()->GetTimeSeconds();
}
void AMainCharacterController::InputKeyboardShiftReleased()
{
if (!bShiftPressed || !mainCharacter)
return;
float holdTime = GetWorld()->GetTimeSeconds() - shiftPressedStartTime;
if (holdTime < dodgeThreshold)
mainCharacter->Dodge();
mainCharacter-> StopRun();
bShiftPressed = false;
}
void AMainCharacterController::Tick(float deltaTime)
{
Super::PlayerTick(deltaTime);
if (bShiftPressed && !mainCharacter->bIsRun)
{
float holdTime = GetWorld()->GetTimeSeconds() - shiftPressedStartTime;
if (holdTime >= runThreshold)
mainCharacter->StartRun();
}
}
Dodge를 구현할때 락온 상태와 락온 상태가 아닐때 두가지로 방향을 구분지었습니다
락온상태일때는 4방향 앞 뒤 오른쪽 왼쪽 비락온상태일때는 닷지가 무조건 앞으로 실행되도록 구현하였습니다
void AMainCharacter::Dodge()
{
if (bIsDodging)
return;
if (guardMode)
return;
FVector inputDir = GetLastMovementInputVector();
FVector dodgeDir;
EDodgeDir dodgeType = EDodgeDir::Forward;
bool bLockOn = lockOnSystem->IsLockOn();
if (bLockOn)
{
AActor* target = lockOnSystem->getCurrentLockOnTarget();
if (!target)
return;
FVector toTarget = (target->GetActorLocation() - GetActorLocation()).GetSafeNormal();
FVector right = FVector::CrossProduct(FVector::UpVector, toTarget);
FVector input = inputDir.GetSafeNormal();
float forwardValue = FVector::DotProduct(input, toTarget);
float rightValue = FVector::DotProduct(input, right);
const float threshold = 0.3f;
if (forwardValue > threshold)
dodgeType = EDodgeDir::Forward;
else if (forwardValue < -threshold)
dodgeType = EDodgeDir::Back;
else if (rightValue > threshold)
dodgeType = EDodgeDir::Right;
else
dodgeType = EDodgeDir::Left;
}
else
{
if (!inputDir.IsNearlyZero())
dodgeDir = inputDir.GetSafeNormal();
else
dodgeDir = GetActorForwardVector();
}
switch (dodgeType)
{
case EDodgeDir::Forward: dodgeDir = GetActorForwardVector(); break;
case EDodgeDir::Back: dodgeDir = -GetActorForwardVector(); break;
case EDodgeDir::Left: dodgeDir = -GetActorRightVector(); break;
case EDodgeDir::Right: dodgeDir = GetActorRightVector(); break;
}
FCharacterAnimDataTable* row = dodgeRowMap[dodgeType];
if (!row || !row->usingAnimation)
return;
UAnimInstance* animInst = GetMesh()->GetAnimInstance();
bIsDodging = true;
float playTime = PlayAnimMontage(row->usingAnimation);
if (playTime <= 0.f)
{
bIsDodging = false;
return;
}
FOnMontageEnded endDel;
endDel.BindUObject(this, &AMainCharacter::OnDodgeMontageEnded);
animInst->Montage_SetEndDelegate(endDel, row->usingAnimation);
FVector launch = dodgeDir * 3000.f;
launch.Z = 0.f;
LaunchCharacter(launch, true, true);
}
또한 데이터테이블에서 RowName이 Dodge인 Dodge Row중에서 이름으로 매핑도 해주었습니다
해당 함수는 전부 BeginPlay에서 캐싱해주었습니다
FName AMainCharacter::GetDodgeRowName(EDodgeDir dir) const
{
switch (dir)
{
case EDodgeDir::Forward: return FName("DodgeForward");
case EDodgeDir::Back: return FName("DodgeBack");
case EDodgeDir::Left: return FName("DodgeLeft");
case EDodgeDir::Right: return FName("DodgeRight");
default: return NAME_None;
}
}
void AMainCharacter::InitDodgeRows()
{
if (!animDataTable)
return;
const EDodgeDir dirs[] =
{
EDodgeDir::Forward,
EDodgeDir::Back,
EDodgeDir::Left,
EDodgeDir::Right
};
for (EDodgeDir dir : dirs)
{
FName rowName = GetDodgeRowName(dir);
FCharacterAnimDataTable* row =animDataTable->FindRow<FCharacterAnimDataTable>(rowName, TEXT("Dodge"));
if (row)
dodgeRows.Add(rowName, row);
}
}
캐릭터의 애니메이션을 담당하는 데이터테이블에 Dodge 타입으로 애니메이션을 추가해주었습니다

결과

락온 상태일때는 적을 기준으로 4방향 앞 뒤 오른쪽 왼쪽 으로 닷지가 가능합니다


영상
'Unreal 프로젝트 다이어리 > 두번째 프로젝트' 카테고리의 다른 글
| Unreal - 그래플링 훅 (0) | 2026.01.08 |
|---|---|
| Unreal - 처형( Execution ) (0) | 2026.01.05 |
| Unreal - 스킬창 & 연동 (0) | 2026.01.01 |
| Unreal - 버프창 (0) | 2025.12.27 |
| Unreal - 퀵슬롯 (0) | 2025.12.27 |