캐릭터가 죽으면 → 메쉬 꺼지고 캡슐 충돌 꺼지고 MovementMode = Flying (이미 되어 있음)
거기서 스페이스(점프 키) 로 상승하고 WSAD 키로 자유롭게 날아다니면서 구경 모드
카메라는 블루프린트에 있으니까 C++에서는 굳이 건드리지 않고 조작 로직만 C++ 으로 처리
➡ 지금 코드에 관전자 같은 입력 처리를 추가
void SpectatorMove(const struct FInputActionValue& Value);
void SpectatorAscend(const struct FInputActionValue& Value);
// 관전 모드 이동 (죽었을 때만 동작)
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ADCCharacter::SpectatorMove);
EIC->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ADCCharacter::SpectatorAscend);
❗MoveAction은 원래 이동에도 쓰이니까 bIsDead 체크로 분기
void ADCCharacter::SpectatorMove(const FInputActionValue& Value)
{
if (!bIsDead) return; // 살아있으면 무시
const FVector2D Axis = Value.Get<FVector2D>();
if (Controller)
{
const FRotator ControlRot = Controller->GetControlRotation();
const FVector Forward = FRotationMatrix(ControlRot).GetUnitAxis(EAxis::X);
const FVector Right = FRotationMatrix(ControlRot).GetUnitAxis(EAxis::Y);
AddMovementInput(Forward, Axis.Y);
AddMovementInput(Right, Axis.X);
}
}
void ADCCharacter::SpectatorAscend(const FInputActionValue& Value)
{
if (!bIsDead) return; // 살아있으면 무시
// 점프 키를 위쪽(Z축 양수) 이동으로 사용
AddMovementInput(FVector::UpVector, 1.0f);
}
void ADCCharacter::OnRep_IsDead()
{
if (bIsDead)
{
GetMesh()->SetVisibility(false);
GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
// 죽으면 비행 모드로 전환
GetCharacterMovement()->SetMovementMode(MOVE_Flying);
}
}
그런데 코드 수정했더니 살아있을 때도 1인칭으로 바뀜
APlayerController->SetViewTarget 사용)MOVE_Flying, 입력 처리 → SpectatorMove, SpectatorAscend 사용protected:
/** 입력 핸들러 */
void Move(const struct FInputActionValue& Value);
void Look(const struct FInputActionValue& Value);
void Dance(const struct FInputActionValue& Value);
void Attack(const struct FInputActionValue& Value);
void StartSlide(const struct FInputActionValue& Value);
// 관전 모드 전용 입력 핸들러
void SpectatorMove(const struct FInputActionValue& Value);
void SpectatorAscend(const struct FInputActionValue& Value);
// 1인칭 카메라 컴포넌트
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Camera")
class UCameraComponent* FirstPersonCamera;
#include "Camera/CameraComponent.h"
#include "GameFramework/PlayerController.h"
ADCCharacter::ADCCharacter()
{
PrimaryActorTick.bCanEverTick = true;
GetCapsuleComponent()->InitCapsuleSize(42.f, 96.f);
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = false;
bUseControllerRotationRoll = false;
GetCharacterMovement()->bOrientRotationToMovement = true;
GetCharacterMovement()->RotationRate = FRotator(0.f, 500.f, 0.f);
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
// 1인칭 카메라 컴포넌트 생성
FirstPersonCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCamera->SetupAttachment(GetCapsuleComponent());
FirstPersonCamera->SetRelativeLocation(FVector(0.f, 0.f, 64.f)); // 눈 위치쯤
FirstPersonCamera->bUsePawnControlRotation = true;
// 기본으론 꺼두기
FirstPersonCamera->SetActive(false);
}
void ADCCharacter::SpectatorMove(const FInputActionValue& Value)
{
if (!bIsDead) return;
const FVector2D Axis = Value.Get<FVector2D>();
if (Controller)
{
const FRotator ControlRot = Controller->GetControlRotation();
const FVector Forward = FRotationMatrix(ControlRot).GetUnitAxis(EAxis::X);
const FVector Right = FRotationMatrix(ControlRot).GetUnitAxis(EAxis::Y);
AddMovementInput(Forward, Axis.Y);
AddMovementInput(Right, Axis.X);
}
}
void ADCCharacter::SpectatorAscend(const FInputActionValue& Value)
{
if (!bIsDead) return;
AddMovementInput(FVector::UpVector, 1.0f);
}
void ADCCharacter::OnRep_IsDead()
{
if (bIsDead)
{
// ---- 죽었을 때 ----
UDCGameInstance* GameInstance = GetWorld() ? Cast<UDCGameInstance>(GetWorld()->GetGameInstance()) : nullptr;
FString Nickname = GameInstance ? GameInstance->GetNickname() : TEXT("알 수 없는 플레이어");
UE_LOG(LogTemp, Warning, TEXT("RepNotify: 플레이어 %s가 사망했습니다!"), *Nickname);
GetMesh()->SetVisibility(false);
GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
GetCharacterMovement()->SetMovementMode(MOVE_Flying);
// 1인칭 카메라 전환
if (APlayerController* PC = Cast<APlayerController>(Controller))
{
if (FirstPersonCamera)
{
FirstPersonCamera->SetActive(true);
PC->SetViewTarget(this);
}
}
}
else
{
// ---- 살아있을 때 (부활 or 시작 시점) ----
GetMesh()->SetVisibility(true);
GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
GetCharacterMovement()->SetMovementMode(MOVE_Walking);
// 1인칭 카메라는 꺼두고, BP의 3인칭 카메라 유지
if (FirstPersonCamera)
{
FirstPersonCamera->SetActive(false);
}
// 필요하다면 여기서 다시 블루프린트 카메라를 ViewTarget으로 지정
if (APlayerController* PC = Cast<APlayerController>(Controller))
{
PC->SetViewTarget(this); // BP 카메라가 따라붙어 있으면 여기서 3인칭 복귀
}
}
}
→ Spectator 전용으로 실행되도록
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ADCCharacter::Move);
EIC->BindAction(LookAction, ETriggerEvent::Triggered, this, &ADCCharacter::Look);
// 죽었을 때 관전 모드 입력
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ADCCharacter::SpectatorMove);
EIC->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ADCCharacter::SpectatorAscend);
여기서 SpectatorMove가 죽었을 때만 동작하도록 if (!bIsDead) return; 으로 막아놔서 충돌 안 남
void ADCCharacter::Move(const FInputActionValue& Value)
{
if (bIsDead) return; // 죽었으면 무시
if (bIsDancing) return;
const FVector2D Axis = Value.Get<FVector2D>();
...
}
void ADCCharacter::SpectatorMove(const FInputActionValue& Value)
{
if (!bIsDead) return;
const FVector2D Axis = Value.Get<FVector2D>();
...
AddMovementInput(Forward, Axis.Y);
AddMovementInput(Right, Axis.X);
}
void ADCCharacter::SpectatorAscend(const FInputActionValue& Value)
{
if (!bIsDead) return;
AddMovementInput(FVector::UpVector, 1.0f);
}
// 입력 바인딩
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ADCCharacter::Move);
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ADCCharacter::SpectatorMove);
EIC->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ADCCharacter::SpectatorAscend);
관전자 모드 성공 ~