[CH4-24] 관전자 모드 구현 - AddMovementInput vs AddActorWorldOffset

김여울·2025년 10월 14일

내일배움캠프

목록 보기
96/139

💥 문제 상황 1

서버와 클라이언트 분리하니까 관전자 모드가 또 사라졌다...

관전자 모드에서 AddActorWorldOffset을 사용하여 직접 액터를 이동시킴

AddActorWorldOffset(InputDir * SpectatorSpeed * GetWorld()->GetDeltaSeconds(), true);

CharacterMovement 컴포넌트를 우회하기 때문에 MOVE_Flying 모드가 제대로 작동하지 않았다

🔧 해결 방법 1

CharacterMovement 시스템을 활용하도록 AddMovementInput으로 변경

void ADCCharacter::SpectatorMove(const FInputActionValue& Value) {
    if (!IsLocallyControlled() || !bIsSpectatorMode) return;
    
    const FVector2D Axis = Value.Get<FVector2D>();
    if (Controller && Axis.SizeSquared() > 0.0f) {
        const FRotator ControlRot = Controller->GetControlRotation();
        
        if (bSpectatorFreeMove) {
            // 자유 비행: 3D 이동
            const FVector Forward = FRotationMatrix(ControlRot).GetUnitAxis(EAxis::X);
            const FVector Right = FRotationMatrix(ControlRot).GetUnitAxis(EAxis::Y);
            AddMovementInput(Forward, Axis.Y);
            AddMovementInput(Right, Axis.X);
        } else {
            // 지상 관전: 수평면만
            const FRotator YawOnlyRot = FRotator(0, ControlRot.Yaw, 0);
            const FVector Forward = FRotationMatrix(YawOnlyRot).GetUnitAxis(EAxis::X);
            const FVector Right = FRotationMatrix(YawOnlyRot).GetUnitAxis(EAxis::Y);
            AddMovementInput(Forward, Axis.Y);
            AddMovementInput(Right, Axis.X);
        }
    }
}

💥 문제 상황 2

Jump 이벤트 중복 호출 문제

스페이스바를 길게 눌렀을 때 Started 이벤트가 반복 호출되어 자유비행 모드가 ON/OFF를 반복하고 Triggered 이벤트가 실행되지 않는 문제가 발생했다.

🔧 해결 방법 2

!bSpectatorFreeMove 조건을 추가하여 자유비행 모드가 OFF일 때만 토글되도록 수정

void ADCCharacter::HandleJumpStarted(const FInputActionValue& Value) {
    if (!IsLocallyControlled()) return;
    
    // 관전자 모드 & 자유비행 OFF일 때만 토글
    if (bIsDead && bIsSpectatorMode && !bSpectatorFreeMove) {
        bSpectatorFreeMove = true;
        return;
    }
    
    // 일반 점프
    if (!bIsDead && !bIsDancing && !GetCharacterMovement()->IsFalling()) {
        Jump();
    }
}

void ADCCharacter::HandleJumpTriggered(const FInputActionValue& Value) {
    if (!IsLocallyControlled()) return;
    
    // 자유비행 모드에서 지속적 상승
    if (bIsDead && bIsSpectatorMode && bSpectatorFreeMove) {
        AddMovementInput(FVector::UpVector, 1.0f);
    }
}

✅ 결과

AddMovementInput을 사용

  • CharacterMovement 컴포넌트의 MovementMode(Walking, Flying 등)를 올바르게 활용
  • GravityScale, MaxFlySpeed 등 설정이 정상 작동
  • 물리 기반 가속/감속이 자연스럽게 적용

AddActorWorldOffset의 한계

  • CharacterMovement를 완전히 우회
  • MovementMode 설정이 무시됨
  • 직접 위치만 변경하므로 부자연스러운 움직임

0개의 댓글