더블 클릭을 통한 달리기
//BaseCharacter.h
FVector2D LastMoveInputDirection;
float LastMoveInputTime;
float DoubleTapThreshold;
uint8 bIsDoubleTab;
//BaseCharacter.cpp
void ABaseCharacter::Move(const FInputActionValue& Value)
{
// input is a Vector2D
FVector2D MovementVector = Value.Get<FVector2D>();
//Detect Double Tap(Sprint)
//Get input direction vector
FVector2D CurrentInputDirection=MovementVector.GetSafeNormal();
// Compare direction (95% match)
if (FVector2D::DotProduct(LastMoveInputDirection, CurrentInputDirection)>0.95f&&bIsDoubleTab)
{
GetCharacterMovement()->MaxWalkSpeed=BalanceStats.MaxRunSpeed;
ServerRPCSetMaxWalkSpeed(BalanceStats.MaxRunSpeed);
}
float CurrentTime=GetWorld()->GetTimeSeconds();
LastMoveInputTime=CurrentTime;
LastMoveInputDirection = CurrentInputDirection;
//Move Logic
if (Controller != nullptr && CurrentCharacterState == ECharacterState::Normal)
{
// find out which way is forward
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
// get forward vector
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
// get right vector
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
FVector MoveDirection = ForwardDirection * MovementVector.Y + RightDirection * MovementVector.X;
// 이동 처리
AddMovementInput(MoveDirection);
}
}
- 이전에 입력된 이동 입력을 캐싱하기 위한 변수 및 더블 탭 감지 제한 시간 변수 선언
ㅡ> LastMoveInputDirection, LastMoveInputTime, DoubleTapThreshold, bIsDoubleTap - 이동 입력에 바인딩된 함수인 Move에서 더블탭에 대한 이벤트 처리
- Move에서 이동 입력이 감지되면 우선 현재 입력의 방향 벡터 저장
- 이후 캐싱된 이전 이동 입력과 DotProduct를 통해 유사도 확인하여 95% 이상이고 더블탭 상황이라면 달리기로 전환
- 이후 입력 시간 및 방향 캐싱하여 저장
- 나머지 이동 로직 동일하게 수행
//BaseCharacter.h
UFUNCTION()
void StartSprint(const FInputActionValue& Value);
UFUNCTION()
void StopSprint(const FInputActionValue& Value);
UFUNCTION(Server,Reliable)
void ServerRPCSetMaxWalkSpeed(const float Value);
//BaseCharacter.cpp
void ABaseCharacter::StartSprint(const FInputActionValue& Value)
{
float CurrentTime=GetWorld()->GetTimeSeconds();
if (CurrentTime-LastMoveInputTime<=DoubleTapThreshold)
{
bIsDoubleTab=true;
}
}
void ABaseCharacter::StopSprint(const FInputActionValue& Value)
{
GetCharacterMovement()->MaxWalkSpeed=BalanceStats.MaxWalkSpeed;
ServerRPCSetMaxWalkSpeed(BalanceStats.MaxWalkSpeed);
bIsDoubleTab=false;
}
void ABaseCharacter::ServerRPCSetMaxWalkSpeed_Implementation(const float Value)
{
GetCharacterMovement()->MaxWalkSpeed=Value;
}
void ABaseCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
// Set up action bindings
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
if (ACharacterController* MyController=Cast<ACharacterController>(GetController()))
{
// Moving
EnhancedInputComponent->BindAction(MyController->MoveAction, ETriggerEvent::Triggered, this, &ABaseCharacter::Move);
EnhancedInputComponent->BindAction(MyController->MoveAction, ETriggerEvent::Started, this, &ABaseCharacter::StartSprint);
EnhancedInputComponent->BindAction(MyController->MoveAction, ETriggerEvent::Completed, this, &ABaseCharacter::StopSprint);
}
}
}
- Move에 해당하는 키 입력이 감지되면 입력 시작단계에서 StartSprint() 호출되도록 바인딩
- 키 입력이 완료(릴리즈)되면 StopSprint() 호출되도록 바인딩
- StartSprint()에서는 현재 마지막 이동 입력 시간과 현재 시간 비교하여 더블탭 인식 시간 내라면 더블탭 상태로 변경
- StopSprint()에서는 이동이 끝난 시점이므로 원래대로 걷기 속도로 설정
ㅡ> 클라이언트에서 즉시 적용 후, ServerRPC로 서버도 동일하게 설정 및 더블탭 상태 해제
정리
예정
- 발사체 관련 공격 옵션 구현
- 애니메이션 몽타주 실행 중 이동
- 발사체 공격 관련 데이터 구조 설계
- 버퍼를 이용한 선입력 액션
- 키 조합을 통한 액션
참고자료
'프로젝트 > CCFF' 카테고리의 다른 글
미친 선인장과 분노의 버섯 - #16 캐릭터 스테이터스와 인게임 HUD 연동 (0) | 2025.04.16 |
---|---|
미친 선인장과 분노의 버섯 - #15 버퍼를 이용한 선입력(예약) & 키 조합을 통한 액션 및 상태에 따른 동작 다변화 (0) | 2025.04.15 |
미친 선인장과 분노의 버섯 - #13 카메라 회전 트러블 슈팅 + 클라이언트 UI 상태 변화에 따른 업데이트 (0) | 2025.04.11 |
미친 선인장과 분노의 버섯 - #12 네트워크 환경에서의 동기화 및 UX(사용자 경험) 개선 (0) | 2025.04.10 |
미친 선인장과 분노의 버섯 - #11 싱글 플레이 -> 멀티 플레이 전환 (네트워크 기반 설계) (0) | 2025.04.09 |