스프링 암(팔)로 카메라를 캐릭터 뒤에 띄워놓고, 충돌/지연 설정으로 “부드럽게 따라오는” 느낌을 만든다.

스프링 암 컴포넌트는 3인칭에서 카메라를 캐릭터와 일정 거리로 유지해주는 역할

스프링 암 끝 소켓 위치에 카메라를 붙인다

소켓 오프셋/타깃 오프셋보다, 스프링 암 자체의 위치·회전을 잡아주는 편이 직관적

카메라 충돌(Probe Size)은 “장애물에 부딪힐 때 판정 반지름”. 너무 크면 쉽게 끼고, 너무 작으면 벽을 뚫는 느낌이 날 수 있음.
폰 제어 회전 사용(Use Pawn Control Rotation)을 켜면, 컨트롤러 요/피치가 스프링 암에도 반영돼 같이 돈다.
카메라 렉(Camera Lag)을 켜면 질량감 있는 “따라오기” 느낌을 줄 수 있음.

Perspective는 원근감 있는 투시, Orthographic은 원근 없는 직교 투영(2D/전략뷰 느낌)

PlatformCharacter 헤더에 필요한 컴포넌트 포인터(스프링암/카메라)를 멤버로 선언


cpp에서 생성/세팅
// PlatformCharacter.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "PlatformCharacter.generated.h"
class USpringArmComponent;
class UCameraComponent;
UCLASS()
class APlatformCharacter : public ACharacter
{
GENERATED_BODY()
public:
APlatformCharacter();
protected:
UPROPERTY(VisibleAnywhere, Category="Camera")
USpringArmComponent* SpringArm;
UPROPERTY(VisibleAnywhere, Category="Camera")
UCameraComponent* FollowCamera;
virtual void BeginPlay() override;
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};
// PlatformCharacter.cpp
#include "PlatformCharacter.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
APlatformCharacter::APlatformCharacter()
{
PrimaryActorTick.bCanEverTick = true;
// 스프링암
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(GetRootComponent());
SpringArm->TargetArmLength = 350.f; // 캐릭터와의 거리
SpringArm->bUsePawnControlRotation = true; // 컨트롤러 회전 반영
SpringArm->bEnableCameraLag = true; // 카메라 따라오기
SpringArm->CameraLagSpeed = 12.f;
SpringArm->ProbeSize = 12.f; // 충돌 프로브 반지름
// 카메라
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
FollowCamera->bUsePawnControlRotation = false; // 카메라 자체는 회전 고정, 팔이 돌아감
// 캐릭터 이동 세팅
UCharacterMovementComponent* Move = GetCharacterMovement();
Move->bOrientRotationToMovement = false; // 캐릭터가 이동방향으로 자동 회전하지 않음
Move->RotationRate = FRotator(0.f, 540.f, 0.f);
// 컨트롤러 요만 캐릭터에 적용(3인칭 보통 구성)
bUseControllerRotationYaw = true;
bUseControllerRotationPitch = false;
bUseControllerRotationRoll = false;
}
void APlatformCharacter::BeginPlay()
{
Super::BeginPlay();
}
void APlatformCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
// Enhanced Input로 바인딩 예정
}

캐릭터 무브먼트에는 중력/가속/마찰/점프 등 다양한 파라미터가 있다. 목적에 맞게 조정

기존(레거시) Input도 사용 가능하지만, UE5에선 Enhanced Input 사용을 권장한다(완전 폐기 아님).

입력 액션(Input Action): “무슨 동작인가”(점프/이동/회전 등) 정의
입력 매핑 컨텍스트(Input Mapping Context): “어떤 키/스틱을 어떤 액션에 매핑할지” 정의

이동용 IAMove 생성 (Value Type: Axis2D/Vector2D)

앞/뒤/좌/우 축을 한 번에 전달하기 위해 Axis2D 사용
bool은 눌렀다/뗐다(디지털), Axis는 연속 값(아날로그 스틱/마우스)

“누적” 세팅은 입력 변환이 연쇄되어 적용되도록 하는 개념 (여러 Modifier/Swizzle 조합 시 유용)

회전용 IARotation 생성 (Value Type: Axis1D/float) — 보통 요(yaw) 회전을 바인딩


입력 매핑 컨텍스트에 방금 만든 액션들을 키/축에 매핑

키를 누르면 기본 입력 값은 1

W는 전진이므로 +1, S는 후진이므로 Negate로 -1

Swizzle(YXZ)은 “순서를 바꿔 특정 축을 꺼내는” 변환. 예) Y를 오른쪽/왼쪽 스트레이프 축으로 사용
E는 +1(오른쪽), Q는 Negate로 -1(왼쪽)

회전 IARotation: D를 +1(우회전), A를 Negate로 -1(좌회전)
입력 리소스(매핑 컨텍스트/액션)를 한 곳에 모아두면 캐릭터에서 참조만 하면 되어 편함.


별도 폴더에서 관리

UPlatformInput 클래스 이름 지정

기본 생성자

#include "InputMappingContext.h"
#include "InputAction.h"
헤더에 포함

퍼블릭 변수로 IMC/IAMove/IARotation 등 노출(에셋 할당용)



참조 복사 후 붙여넣기

나머지도 동일하게 채우기
아래처럼 “데이터 에셋” 형태로 두면 사용하기 좋다.
// PlatformInput.h
#pragma once
#include "Engine/DataAsset.h"
#include "PlatformInput.generated.h"
class UInputMappingContext;
class UInputAction;
UCLASS(BlueprintType)
class UPlatformInput : public UDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Input")
UInputMappingContext* MappingContext = nullptr;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Input")
UInputAction* IA_Move = nullptr;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Input")
UInputAction* IA_Rotation = nullptr;
// 필요 시 점프/공격 등 추가
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Input")
UInputAction* IA_Jump = nullptr;
};

PlatformCharacter.cpp에서 위 입력 리소스를 받아와 등록·바인딩


이 코드는 캐릭터가 게임에 등장할 때(BeginPlay) 플레이어 입력을 받을 수 있도록 Enhanced Input 시스템에 입력 매핑 컨텍스트를 등록하는 과정이에요.
Super::BeginPlay();
ACharacter)의 BeginPlay()를 먼저 호출해서 기본 초기화 로직을 실행합니다.APlayerController* PlyerController = Cast<APlayerController>(GetController());
Cast<>()는 타입 변환 함수인데, 안전하게 형변환을 해주고 실패하면 nullptr을 반환합니다.PlayerController가 있을 것이고, AI가 조종 중이면 없을 수도 있어요.if (IsValid(PlyerController))
IsValid()는 UObject가 null이 아니고 파괴되지 않은 상태인지 확인하는 함수입니다.UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlyerController->GetLocalPlayer());
Subsystem은 실제로 입력 매핑을 관리해주는 객체예요.GetLocalPlayer() → 현재 플레이어의 로컬 플레이어 객체를 반환.ULocalPlayer::GetSubsystem<>() → 특정 타입의 서브시스템(여기선 입력 서브시스템)을 가져옴.const UPlatformInput* InputCDO = GetDefault<UPlatformInput>();
GetDefault<>()는 해당 클래스 타입의 **CDO(Class Default Object)**를 가져옵니다.UPlatformInput 클래스의 기본 인스턴스를 얻어오는 거죠.const인 이유는 CDO는 기본값만 참고하고 수정하면 안 되기 때문입니다.Subsystem->AddMappingContext(InputCDO->mContext, 0);
mContext)를 Enhanced Input 시스템에 등록하는 단계입니다.mContext는 보통 Input Mapping Context 애셋을 가리킵니다.0은 우선순위입니다. 숫자가 클수록 높은 우선순위를 가집니다.이 함수는 게임 시작 시, 해당 캐릭터가 플레이어 입력을 받을 수 있도록 UPlatformInput의 기본 입력 매핑 컨텍스트를 Enhanced Input 서브시스템에 등록하는 초기화 과정입니다.