콘텐츠로 이동

UE5 Gameplay Camera 시스템

UCLASS()
class AMyCharacter : public ACharacter {
GENERATED_BODY()
UPROPERTY(VisibleAnywhere) USpringArmComponent* SpringArm;
UPROPERTY(VisibleAnywhere) UCameraComponent* Camera;
public:
AMyCharacter() {
SpringArm = CreateDefaultSubobject<USpringArmComponent>("SpringArm");
SpringArm->SetupAttachment(RootComponent);
SpringArm->TargetArmLength = 400.f;
SpringArm->bUsePawnControlRotation = true;
SpringArm->bEnableCameraLag = true;
SpringArm->CameraLagSpeed = 10.f;
SpringArm->bEnableCameraRotationLag = true;
SpringArm->CameraRotationLagSpeed = 15.f;
Camera = CreateDefaultSubobject<UCameraComponent>("Camera");
Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
}
};
// 달릴 때 카메라 당기기
void AMyCharacter::SetSprinting(bool bSprinting) {
float TargetLength = bSprinting ? 600.f : 400.f;
SpringArm->TargetArmLength = FMath::FInterpTo(
SpringArm->TargetArmLength, TargetLength, DeltaTime, 5.f);
}
// 속도에 따른 FOV 변화 (속도감 연출)
void AMyCharacter::Tick(float DeltaTime) {
Super::Tick(DeltaTime);
float Speed = GetVelocity().Size();
float TargetFOV = FMath::Lerp(90.f, 100.f, Speed / MaxSpeed);
float CurrentFOV = Camera->FieldOfView;
Camera->FieldOfView = FMath::FInterpTo(CurrentFOV, TargetFOV, DeltaTime, 8.f);
}
// CameraShake 에셋 생성 (레거시)
UCLASS()
class UHitCameraShake : public ULegacyCameraShake {
GENERATED_BODY()
UHitCameraShake() {
OscillationDuration = 0.3f;
OscillationBlendInTime = 0.05f;
OscillationBlendOutTime = 0.1f;
RotOscillation.Pitch = { 3.f, 10.f, EWaveOscillatorClampingType::None };
RotOscillation.Yaw = { 2.f, 8.f, EWaveOscillatorClampingType::None };
}
};
// 재생
APlayerController* PC = GetWorld()->GetFirstPlayerController();
PC->ClientStartCameraShake(UHitCameraShake::StaticClass(), 1.0f);
// 위치 기반 강도 (거리에 따라 약해짐)
PC->ClientStartCameraShakeFromSource(
UExplosionCameraShake::StaticClass(),
ShakeSourceComponent);
// 시네마틱 카메라로 블렌딩
void AMyGameMode::SwitchToEventCamera(ACameraActor* EventCam, float BlendTime) {
APlayerController* PC = GetWorld()->GetFirstPlayerController();
PC->SetViewTargetWithBlend(EventCam, BlendTime, VTBlend_Cubic);
}
// 플레이어 카메라로 복귀
void AMyGameMode::ReturnToPlayerCamera(float BlendTime) {
APlayerController* PC = GetWorld()->GetFirstPlayerController();
PC->SetViewTargetWithBlend(PC->GetPawn(), BlendTime, VTBlend_EaseInOut, 2.f);
}
UCLASS()
class USpeedLinesModifier : public UCameraModifier {
GENERATED_BODY()
virtual bool ModifyCamera(float DeltaTime, FMinimalViewInfo& InOutPOV) override {
ACharacter* Char = Cast<ACharacter>(GetViewTarget());
if (!Char) return false;
float Speed = Char->GetVelocity().Size();
float SpeedRatio = FMath::Clamp(Speed / 1000.f, 0.f, 1.f);
// FOV 살짝 증가 (속도감)
InOutPOV.FOV += SpeedRatio * 5.f;
return false; // 다른 Modifier도 처리
}
};
// 컨트롤러에 추가
PC->PlayerCameraManager->AddNewCameraModifier(USpeedLinesModifier::StaticClass());
FRotator AMyPlayerController::GetAdjustedAimRotation(FRotator BaseRot) {
// 조준 근처의 적 탐지
TArray<FHitResult> Hits;
FVector Start = PlayerCameraManager->GetCameraLocation();
FVector End = Start + BaseRot.Vector() * 5000.f;
GetWorld()->SweepMultiByChannel(Hits, Start, End,
FQuat::Identity, ECC_Pawn,
FCollisionShape::MakeSphere(50.f));
for (const FHitResult& Hit : Hits) {
if (AEnemy* Enemy = Cast<AEnemy>(Hit.GetActor())) {
FRotator ToEnemy = UKismetMathLibrary::FindLookAtRotation(
Start, Enemy->GetActorLocation());
// 5도 이내면 부드럽게 보정
if (FMath::Abs(FRotator::NormalizeAxis(BaseRot.Yaw - ToEnemy.Yaw)) < 5.f)
return FMath::RInterpTo(BaseRot, ToEnemy, GetWorld()->DeltaTimeSeconds, 10.f);
}
}
return BaseRot;
}
  • USpringArmComponent CameraLag/RotationLag로 자연스러운 카메라 추적
  • 속도에 따른 FOV/TargetArmLength 보간으로 속도감 연출
  • UCameraModifier로 카메라 파이프라인에 후처리 효과 주입
  • SetViewTargetWithBlend로 이벤트 카메라 전환 시 부드러운 블렌딩
  • 카메라 셰이크는 거리 기반 소스 컴포넌트로 현실감 추가