캐릭터 동작 구현과 입력 처리 | [언리얼 엔진 C++ (Unreal Engine C++)]

2026. 6. 9. 12:32·Unreal Engine/UE 기초

 

캐릭터 동작 구현과 입력 처리

 


 

캐릭터 동작 구현과 입력 처리 관련 이전에 한 것들

 

GameMode Class 가 관리하고 있는 것: Character Class, Player Controller

  • Character Class 가 월드에 스폰 되도록
  • Player Controller: 사용자의 입력과 Character 사이에의 연결 (Poses 빙의)
  • IMC 활성화

 

[Unreal Engine/UE 기초] - GameMode | [언리얼 엔진 C++ (Unreal Engine C++)]

 

GameMode | [언리얼 엔진 C++ (Unreal Engine C++)]

GameMode GameMode 이해하기 1️⃣ GameMode란?GameMode는 게임의 전반적인 규칙과 흐름을 총괄 관리하는, 일종의 컨트롤 타워 역할을 하는 클래스입니다.다른 곳에서 사용하는 GameManager 와 동일하다고 생

devcol.tistory.com

 

[Unreal Engine/UE 기초] - Character 클래스 구현 | [언리얼 엔진 C++ (Unreal Engine C++)]

 

Character 클래스 구현 | [언리얼 엔진 C++ (Unreal Engine C++)]

Character 클래스 구현 Pawn과 Character Class 정의 1️⃣ Pawn 클래스란?Pawn은 플레이어 혹은 AI가 “소유( Possess )”할 수 있는 가장 상위 클래스입니다. 즉, 엔진에서 “무언가를 조종한다”라고 할 때

devcol.tistory.com

 

[Unreal Engine/UE 기초] - Enhanced Input System 입력 매핑 구현하기 | [언리얼 엔진 C++ (Unreal Engine C++)]

 

Enhanced Input System 입력 매핑 구현하기 | [언리얼 엔진 C++ (Unreal Engine C++)]

Enhanced Input System 입력 매핑 구현하기 PlayerController, IMC, IA PlayerController 이해하기 1️⃣ PlayerController란?PlayerController는 사용자가 키보드, 마우스, 게임패드 등에서 입력을 받으면, 그 입력을 해석하

devcol.tistory.com

 

 


 

Character 클래스에 액션 바인딩 추가하기

1️⃣ 캐릭터 클래스에서 입력 액션 연결의 개념

  • PlayerController는 "키나 마우스 입력"을 감지하고, 각 입력 액션 InputAction(IA)을 활성화해줄 뿐입니다. 그다음 캐릭터 클래스(MainCharacter)에서 “어떤 함수가 호출될지”를 바인딩 (연결) 해주어야 최종적으로 동작이 이루어집니다.
  • 정리하자면
    1. PlayerController는 MainInputMappingContext(IMC)를 활성화합니다.
    2. 해당 IMC에는 IA_Move, IA_Jump 등의 UInputAction들이 키보드/마우스와 맵핑되어 있습니다.
    3. 캐릭터가 SetupPlayerInputComponent() 함수를 통해 “각 액션이 발생했을 때 어떤 함수를 실행할지”를 등록해둡니다.
    4. 이렇게 등록한 함수들이, 실제로 움직이거나 점프하는 등 캐릭터 동작을 수행합니다.

 

2️⃣ 캐릭터에 액션 바인딩 추가하기

MainChacter.h

더보기
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MainCharacter.generated.h"

// 미리 선언
// 전방 선언(Forward Declaration) 
class USpringArmComponent; // 스프링 암 관련 클래스 헤더
class UCameraComponent; // 카메라 관련 클래스 전방 선언


// Enhanced Input에서 액션 값을 받을 때 사용하는 구조체
struct FInputActionValue;

UCLASS()
class BC_CH3_ASSIGNMENT_4_API AMainCharacter : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	AMainCharacter();
	
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
	USpringArmComponent* SpringArmComp  = nullptr;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
	UCameraComponent* CameraComp = nullptr;
	


	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

protected:

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	
	//여기서 인자값을 참조로 받는 이유는 구조체는 크기때문에 참조를 안하고 직접 가져오면 복사비용이 커서 성능 저하 문제가 발생합니다
	// IA_Move와 IA_Jump 등을 처리할 함수 원형
    // Enhanced Input에서 액션 값은 FInputActionValue로 전달됩니다.
	// UFUNCTION()을 붙이지 않으면 바인딩에 실패할 수 있습니다.
	// 블루프린트 접근성을 설정하지 않았더라도, 기본적으로 메타데이터가 생성됩니다.
	
	UFUNCTION()
	void Move(const FInputActionValue& value);
	
	UFUNCTION()
	void Look(const FInputActionValue& value);
	
	// on off 의 형태의 것들은 그냥 나눠 주는 것이 좋다
	// 왜냐하면 이전에는 세세하게 처리하기가 상당이 까다로웠는데
	// EnhancedInputSystem은 그것들을 매우 편하게 변경해주었기 때문에 왠만하면 나눠 주는 것이 좋다
	UFUNCTION()
	void StartJump(const FInputActionValue& value);
	UFUNCTION()
	void StopJump(const FInputActionValue& value);
	
	UFUNCTION()
	void StartSprint(const FInputActionValue& value);
	UFUNCTION()
	void StopSprint(const FInputActionValue& value);
	
};

 

MainCharacter.cpp

더보기
#include "MainCharacter.h"

//
#include "EnhancedInputComponent.h"
#include "MainPlayerController.h"

// 카메라, 스프링 암 실제 구현이 필요한 경우라서 include
// 전방 선언(Forward Declaration) 한것 여기서 (실질적으로 사용하는곳) 포함
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"

AMainCharacter::AMainCharacter()
{
 	
	PrimaryActorTick.bCanEverTick = true;
	
	
	// (1) 스프링 암 생성
	SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
	// 스프링 암을 루트 컴포넌트 (CapsuleComponent)에 부착
	SpringArmComp->SetupAttachment(RootComponent);
	// 캐릭터와 카메라 사이의 거리 기본값 300으로 설정
	SpringArmComp->TargetArmLength = 300.0f;  
	// 컨트롤러 회전에 따라 스프링 암도 회전하도록 설정
	SpringArmComp->bUsePawnControlRotation = true;  
	
	
	//

	// (2) 카메라 컴포넌트 생성
	CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
	// 스프링 암의 소켓 위치에 카메라를 부착
	CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);
	// 카메라는 스프링 암의 회전을 따르므로 PawnControlRotation은 꺼둠
	CameraComp->bUsePawnControlRotation = false;
	
	
}

// Called when the game starts or when spawned
void AMainCharacter::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AMainCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

// Called to bind functionality to input
void AMainCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
	// Enhanced InputComponent로 캐스팅
    if (UEnhancedInputComponent* EnhancedInput = Cast<UEnhancedInputComponent>(PlayerInputComponent))
    {
        // IA를 가져오기 위해 현재 소유 중인 Controller를 AMainPlayerController로 캐스팅
        if (AMainPlayerController* PlayerController = Cast<AMainPlayerController>(GetController()))
        {
        	// null check
            if (PlayerController->MoveAction)
            {
                // IA_Move 액션 키를 "키를 누르고 있는 동안" Move() 호출
                EnhancedInput->BindAction(
                    PlayerController->MoveAction,
                    ETriggerEvent::Triggered,
                    this,
                    &AMainCharacter::Move
                );
            }
            
            if (PlayerController->JumpAction)
            {
                // IA_Jump 액션 키를 "키를 누르고 있는 동안" StartJump() 호출
                EnhancedInput->BindAction(
                    PlayerController->JumpAction,
                    ETriggerEvent::Triggered,
                    this,
                    &AMainCharacter::StartJump
                );
                
                // IA_Jump 액션 키에서 "손을 뗀 순간" StopJump() 호출
                EnhancedInput->BindAction(
                    PlayerController->JumpAction,
                    ETriggerEvent::Completed,
                    this,
                    &AMainCharacter::StopJump
                );
            }
            
            if (PlayerController->LookAction)
            {
                // IA_Look 액션 마우스가 "움직일 때" Look() 호출
                EnhancedInput->BindAction(
                    PlayerController->LookAction,
                    ETriggerEvent::Triggered,
                    this,
                    &AMainCharacter::Look
                );
            }
            
            if (PlayerController->SprintAction)
            {
                // IA_Sprint 액션 키를 "누르고 있는 동안" StartSprint() 호출
                EnhancedInput->BindAction(
                    PlayerController->SprintAction,
                    ETriggerEvent::Triggered, 
                    this, 
                    &AMainCharacter::StartSprint
                );
                // IA_Sprint 액션 키에서 "손을 뗀 순간" StopSprint() 호출
                EnhancedInput->BindAction(
                    PlayerController->SprintAction, 
                    ETriggerEvent::Completed, 
                    this, 
                    &AMainCharacter::StopSprint
                );
            }    
        }
    }

}

 

  • FInputActionValue: Enhanced Input에서 액션 값 (축 이동값, 마우스 이동량 등)을 전달할 때 사용하는 구조체로, IA에서 설정한 Value Type입니다.
    • 여기서 인자값을 참조로 받는 이유는 구조체는 크기때문에 참조를 안하고 직접 가져오면 복사비용이 커서 성능 저하 문제가 발생합니다
  • UFUNCTION(): 입력 바인딩 함수는 언리얼 엔진 리플렉션 시스템과 연동되어야 합니다. UFUNCTION()을 붙이지 않으면 바인딩에 실패할 수 있습니다.
    • 블루프린트 접근성을 설정하지 않았더라도, 기본적으로 메타데이터가 생성됩니다.
    • 언리얼 엔진의 입력 처리 시스템은 바인딩된 함수가 리플렉션 시스템을 통해 접근 가능한지 확인합니다.
  • BindAction 함수
    • 첫 번째 인자: 어떤 UInputAction과 연결할지. (예: MoveAction)
    • 두 번째 인자: 액션이 발생하는 트리거 이벤트 (Triggered, Ongoing, Completed 등).
    • 세 번째/네 번째 인자: 액션 발생 시 실행할 객체(this)와 함수 포인터.
  • 점프와 스프린트 함수 분리
    • “키를 누를 때”와 “뗄 때”가 다르게 처리될 수 있으므로 두 함수로 분리했습니다.
    • on off 의 형태의 것들은 그냥 나눠 주는 것이 좋다  왜냐하면 이전에는 세세하게 처리하기가 상당이 까다로웠는데, EnhancedInputSystem은 그것들을 매우 편하게 변경해주었기 때문에, 왠만하면 나눠 주는 것이 좋습니다.

 

 


이동 함수 구현하기

Move 함수 

더보기
void AMainCharacter::Move(const FInputActionValue& value)
{
    // 컨트롤러가 있어야 방향 계산이 가능
    if (!Controller) return;

    // Value는 Axis2D로 설정된 IA_Move의 입력값 (WASD)을 담고 있음
    // 예) (X=1, Y=0) → 전진 / (X=-1, Y=0) → 후진 / (X=0, Y=1) → 오른쪽 / (X=0, Y=-1) → 왼쪽
    const FVector2D MoveInput = value.Get<FVector2D>();

    // IsNearlyZero
    // 부동소수점들은 딱 0으로 안 떨어 질 수도 있기 때문에 작은 오차들은 0으로 처리 하기 위한 함수
    if (!FMath::IsNearlyZero(MoveInput.X))
    {     
       // 캐릭터가 바라보는 방향(정면)으로 X축 이동
       AddMovementInput(GetActorForwardVector(), MoveInput.X);
    }

    if (!FMath::IsNearlyZero(MoveInput.Y))
    {
       // 캐릭터의 오른쪽 방향으로 Y축 이동
       AddMovementInput(GetActorRightVector(), MoveInput.Y);
    }
}
  • if (!Controller) return;
    • 컨트롤러 여부 확인
    • 나중에 혹시나 AI에 의해 조종/조작 될 수 도 있기에
  • FInputActionValue::Get<FVector2D>()
    • IA_Move가 Axis2D로 설정되어 있으므로, 2차원 벡터 형태로 입력이 들어옵니다.
    • W(앞) / S(뒤) / D(오른쪽) / A(왼쪽)을 동시에 누를 수도 있으므로, (1,1) 같은 형태도 가능하죠.
  • if (!FMath::IsNearlyZero(MoveInput.X))
    • 부동소수점들은 딱 0으로 안 떨어 질 수도 있기 때문에, 작은 오차들은 0으로 처리 하기 위한 함수
  • AddMovementInput(방향, 크기)
    • 첫 번째 파라미터: 월드 좌표 기준 이동 방향(Forward, Right 등)
    • 두 번째 파라미터: 이동 스케일(속도)
    • 내부적으로 CharacterMovementComponent가 이 요청을 받아 속도를 계산하고, 실제 이동을 구현합니다
    • GetActorForwardVector(), GetActorRightVector(): 등 방향을 가져오려면 컨트롤러가 기본적으로 있어야합니다.

 

점프 함수 구현하기

StartJump, StopJump 함수

더보기
void AMainCharacter::StartJump(const FInputActionValue& value)
{
	// Jump 함수는 Character가 기본 제공
	if (value.Get<bool>())
	{
		Jump();
	}
}
void AMainCharacter::StopJump(const FInputActionValue& value)
{	
	// StopJumping 함수도 Character가 기본 제공
	if (!value.Get<bool>())
	{
		StopJumping();
	}	
}
  • value.Get<bool>()
    • Enhanced Input System에서 전달된 입력 값을 bool로 가져옵니다.
    • 이 값은 점프 키(예: 스페이스바)가 눌렸는지 여부를 나타냅니다.
      • true: 키가 눌림.
      • false: 키가 눌리지 않음.
  • StopJumping() , Jump()
    • Character 클래스에서 기본 제공되는 함수로, 캐릭터가 점프를 하거나 멈추도록 만들어줍니다.

 

 


 

시점 회전 구현하기

Look 함수 

더보기
void AMainCharacter::Look(const FInputActionValue& value)
{
	// 마우스의 X, Y 움직임을 2D 축으로 가져옴
	FVector2D LookInput = value.Get<FVector2D>();

	// X는 좌우 회전 (Yaw), Y는 상하 회전 (Pitch)
	// 좌우 회전
	AddControllerYawInput(LookInput.X);
	
	// 상하 회전
	// IA에서 반전해둔 상태
	// 여기엔 추후 변경 가능한 옵션 추가해주자
	AddControllerPitchInput(LookInput.Y);
}

 

  • AddControllerYawInput(): 카메라의 Yaw 축 (수평 회전)을 변경
    • 마우스를 좌우로 움직이면 Yaw 으로 캐릭터 시점이 돌아갑니다.
  • AddControllerPitchInput(): 카메라의 Pitch 축 (수직 회전)을 변경
    • 보통 IA 반전해서 상용 (하지만 이것은 취향차이 + 옵션에서 변경가능 하게 해줍니다)
    • 마우스를 위아래로 움직이면 Pitch가 적용되어 카메라가 위/아래로 움직입니다.
  • 실제 어느 방향으로 얼마나 회전할지는, 프로젝트 세팅 → Input → Mouse Sensitivity나 LookInput에 곱해줄 스케일 (Modifiers)을 통해 조정할 수 있습니다.
  •  

 


 

스프린트 동작 구현하기

스프린트 관련 멤버 변수 및 함수 설정하기

수정된 부분만

더보기

.h

	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
	float NormalSpeed; // 기본 걷기 속도
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
	float SprintSpeedMultiplier;  // "기본 속도" 대비 몇 배로 빠르게 달릴지
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Movement")
	float SprintSpeed; 	// 실제 스프린트 속도 SprintSpeed= NormalSpeed * SprintSpeedMultiplier

 .cpp

#include "GameFramework/CharacterMovementComponent.h" // GetCharacterMovement() 사용을 위해


ASpartaCharacter::ASpartaCharacter()
{
		PrimaryActorTick.bCanEverTick = false;

    SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
    SpringArmComp->SetupAttachment(RootComponent);
    SpringArmComp->TargetArmLength = 300.0f;
    SpringArmComp->bUsePawnControlRotation = true;

    CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
    CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);
    CameraComp->bUsePawnControlRotation = false;

	// === 추가된 부분 ===
    NormalSpeed = 600.0f;
    SprintSpeedMultiplier = 1.5f;
    SprintSpeed = NormalSpeed * SprintSpeedMultiplier;

    GetCharacterMovement()->MaxWalkSpeed = NormalSpeed;
}


void AMainCharacter::StartSprint(const FInputActionValue& value)
{
    // Shift 키를 누른 순간 이 함수가 호출된다고 가정
    // 스프린트 속도를 적용
    if (GetCharacterMovement())
    {
       GetCharacterMovement()->MaxWalkSpeed = SprintSpeed;
    }

}
void AMainCharacter::StopSprint(const FInputActionValue& value)
{
    // Shift 키를 뗀 순간 이 함수가 호출
    // 평상시 속도로 복귀
    if (GetCharacterMovement())
    {
       GetCharacterMovement()->MaxWalkSpeed = NormalSpeed;
    }
}

 

전체 코드

더보기

.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MainCharacter.generated.h"

// 미리 선언
// 전방 선언(Forward Declaration) 
class USpringArmComponent; // 스프링 암 관련 클래스 헤더
class UCameraComponent; // 카메라 관련 클래스 전방 선언


// Enhanced Input에서 액션 값을 받을 때 사용하는 구조체
struct FInputActionValue;

UCLASS()
class BC_CH3_ASSIGNMENT_4_API AMainCharacter : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	AMainCharacter();
	
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
	USpringArmComponent* SpringArmComp  = nullptr;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
	UCameraComponent* CameraComp = nullptr;
	


	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

protected:

	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
	float NormalSpeed; // 기본 걷기 속도
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
	float SprintSpeedMultiplier;  // "기본 속도" 대비 몇 배로 빠르게 달릴지
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Movement")
	float SprintSpeed; 	// 실제 스프린트 속도 SprintSpeed= NormalSpeed * SprintSpeedMultiplier
	
	
	
	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	
	//여기서 인자값을 참조로 받는 이유는 구조체는 크기때문에 참조를 안하고 직접 가져오면 복사비용이 커서 성능 저하 문제가 발생합니다
	// IA_Move와 IA_Jump 등을 처리할 함수 원형
    // Enhanced Input에서 액션 값은 FInputActionValue로 전달됩니다.
	// UFUNCTION()을 붙이지 않으면 바인딩에 실패할 수 있습니다.
	// 블루프린트 접근성을 설정하지 않았더라도, 기본적으로 메타데이터가 생성됩니다.
	
	UFUNCTION()
	void Move(const FInputActionValue& value);
	
	UFUNCTION()
	void Look(const FInputActionValue& value);
	
	// on off 의 형태의 것들은 그냥 나눠 주는 것이 좋다
	// 왜냐하면 이전에는 세세하게 처리하기가 상당이 까다로웠는데
	// EnhancedInputSystem은 그것들을 매우 편하게 변경해주었기 때문에 왠만하면 나눠 주는 것이 좋다
	UFUNCTION()
	void StartJump(const FInputActionValue& value);
	UFUNCTION()
	void StopJump(const FInputActionValue& value);
	
	UFUNCTION()
	void StartSprint(const FInputActionValue& value);
	UFUNCTION()
	void StopSprint(const FInputActionValue& value);
	
};

 

.cpp

#include "MainCharacter.h"

//
#include "EnhancedInputComponent.h"
#include "MainPlayerController.h"

// 카메라, 스프링 암 실제 구현이 필요한 경우라서 include
// 전방 선언(Forward Declaration) 한것 여기서 (실질적으로 사용하는곳) 포함
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h" 

//
#include "GameFramework/CharacterMovementComponent.h" // GetCharacterMovement() 사용을 위해


AMainCharacter::AMainCharacter()
{
 	
	PrimaryActorTick.bCanEverTick = true;
	
	
	// (1) 스프링 암 생성
	SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
	// 스프링 암을 루트 컴포넌트 (CapsuleComponent)에 부착
	SpringArmComp->SetupAttachment(RootComponent);
	// 캐릭터와 카메라 사이의 거리 기본값 300으로 설정
	SpringArmComp->TargetArmLength = 300.0f;  
	// 컨트롤러 회전에 따라 스프링 암도 회전하도록 설정
	SpringArmComp->bUsePawnControlRotation = true;  
	
	
	//

	// (2) 카메라 컴포넌트 생성
	CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
	// 스프링 암의 소켓 위치에 카메라를 부착
	CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);
	// 카메라는 스프링 암의 회전을 따르므로 PawnControlRotation은 꺼둠
	CameraComp->bUsePawnControlRotation = false;
	
	// Movements & Sprint Speed
	
	NormalSpeed = 600.0f;
	SprintSpeedMultiplier = 1.75f;
	SprintSpeed = NormalSpeed * SprintSpeedMultiplier;

	
	// #include "GameFramework/CharacterMovementComponent.h" 추가해야함
	// MaxWalkSpeed 변경시 캐릭터 이동속도가 즉시 변경
	GetCharacterMovement()->MaxWalkSpeed = NormalSpeed;
	
}

// Called when the game starts or when spawned
void AMainCharacter::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AMainCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

// Called to bind functionality to input
void AMainCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
	// Enhanced InputComponent로 캐스팅
    if (UEnhancedInputComponent* EnhancedInput = Cast<UEnhancedInputComponent>(PlayerInputComponent))
    {
        // IA를 가져오기 위해 현재 소유 중인 Controller를 AMainPlayerController로 캐스팅
        if (AMainPlayerController* PlayerController = Cast<AMainPlayerController>(GetController()))
        {
        	// null check
            if (PlayerController->MoveAction)
            {
                // IA_Move 액션 키를 "키를 누르고 있는 동안" Move() 호출
                EnhancedInput->BindAction(
                    PlayerController->MoveAction,
                    ETriggerEvent::Triggered,
                    this,
                    &AMainCharacter::Move
                );
            }
            
            if (PlayerController->JumpAction)
            {
                // IA_Jump 액션 키를 "키를 누르고 있는 동안" StartJump() 호출
                EnhancedInput->BindAction(
                    PlayerController->JumpAction,
                    ETriggerEvent::Triggered,
                    this,
                    &AMainCharacter::StartJump
                );
                
                // IA_Jump 액션 키에서 "손을 뗀 순간" StopJump() 호출
                EnhancedInput->BindAction(
                    PlayerController->JumpAction,
                    ETriggerEvent::Completed,
                    this,
                    &AMainCharacter::StopJump
                );
            }
            
            if (PlayerController->LookAction)
            {
                // IA_Look 액션 마우스가 "움직일 때" Look() 호출
                EnhancedInput->BindAction(
                    PlayerController->LookAction,
                    ETriggerEvent::Triggered,
                    this,
                    &AMainCharacter::Look
                );
            }
            
            if (PlayerController->SprintAction)
            {
                // IA_Sprint 액션 키를 "누르고 있는 동안" StartSprint() 호출
                EnhancedInput->BindAction(
                    PlayerController->SprintAction,
                    ETriggerEvent::Triggered, 
                    this, 
                    &AMainCharacter::StartSprint
                );
                // IA_Sprint 액션 키에서 "손을 뗀 순간" StopSprint() 호출
                EnhancedInput->BindAction(
                    PlayerController->SprintAction, 
                    ETriggerEvent::Completed, 
                    this, 
                    &AMainCharacter::StopSprint
                );
            }    
        }
    }

}

void AMainCharacter::Move(const FInputActionValue& value)
{
	// 컨트롤러가 있어야 방향 계산이 가능
	if (!Controller) return;

	// Value는 Axis2D로 설정된 IA_Move의 입력값 (WASD)을 담고 있음
	// 예) (X=1, Y=0) → 전진 / (X=-1, Y=0) → 후진 / (X=0, Y=1) → 오른쪽 / (X=0, Y=-1) → 왼쪽
	const FVector2D MoveInput = value.Get<FVector2D>();

	// IsNearlyZero
	// 부동소수점들은 딱 0으로 안 떨어 질 수도 있기 때문에 작은 오차들은 0으로 처리 하기 위한 함수
	if (!FMath::IsNearlyZero(MoveInput.X))
	{		
		// 캐릭터가 바라보는 방향(정면)으로 X축 이동
		AddMovementInput(GetActorForwardVector(), MoveInput.X);
	}

	if (!FMath::IsNearlyZero(MoveInput.Y))
	{
		// 캐릭터의 오른쪽 방향으로 Y축 이동
		AddMovementInput(GetActorRightVector(), MoveInput.Y);
	}
}

void AMainCharacter::Look(const FInputActionValue& value)
{
	// 마우스의 X, Y 움직임을 2D 축으로 가져옴
	FVector2D LookInput = value.Get<FVector2D>();

	// X는 좌우 회전 (Yaw), Y는 상하 회전 (Pitch)
	// 좌우 회전
	AddControllerYawInput(LookInput.X);
	
	// 상하 회전
	// IA에서 반전해둔 상태
	// 여기엔 추후 변경 가능한 옵션 추가해주자
	AddControllerPitchInput(LookInput.Y);
}

void AMainCharacter::StartJump(const FInputActionValue& value)
{
	// Jump 함수는 Character가 기본 제공
	if (value.Get<bool>())
	{
		Jump();
	}
}
void AMainCharacter::StopJump(const FInputActionValue& value)
{	
	// StopJumping 함수도 Character가 기본 제공
	if (!value.Get<bool>())
	{
		StopJumping();
	}	
}

void AMainCharacter::StartSprint(const FInputActionValue& value)
{
	// Shift 키를 누른 순간 이 함수가 호출된다고 가정
	// 스프린트 속도를 적용
	if (GetCharacterMovement())
	{
		GetCharacterMovement()->MaxWalkSpeed = SprintSpeed;
	}

}
void AMainCharacter::StopSprint(const FInputActionValue& value)
{
	// Shift 키를 뗀 순간 이 함수가 호출
	// 평상시 속도로 복귀
	if (GetCharacterMovement())
	{
		GetCharacterMovement()->MaxWalkSpeed = NormalSpeed;
	}
}

 

 

  • 언리얼 엔진의 CharacterMovementComponent에는 MaxWalkSpeed라는 속성이 있습니다. MaxWalkSpeed 값을 변경하면, 캐릭터의 이동 속도가 즉시 바뀝니다.
  • Shift 키를 누르는 순간 MaxWalkSpeed를 “빠른 속도”로, Shift 키를 뗄 때 (또는 놓았을 때) 다시 “기본 속도”로 돌려놓으면, 스프린트 효과를 낼 수 있습니다.
  • 우선, 캐릭터 클래스 SpartaCharacter.h 파일에서 스프린트 관련 멤버 변수를 추가해야 합니다.
    • SprintSpeedMultiplier
      • 예: 1.75f → “기본 속도의 1.75배”
      • “Shift 키를 누른 상태”에서 이동 속도가 얼마나 빨라질지 결정
    • SprintSpeed
      • “Shift 키를 누른 상태”에서 적용할 실제 속도값
      • 숫자를 고정해두거나, 생성자에서 SprintSpeed = NormalSpeed * SprintSpeedMultiplier;로 연산할 수도 있습니다.
  • GetCharacterMovement() : ACharacter 클래스에 기본 내장된 함수로, UCharacterMovementComponent* 포인터를 반환합니다.여기서 MaxWalkSpeed 등의 이동 관련 설정을 바꿀 수 있습니다.
  • AddMovementInput()는 키 입력 때마다 “어느 방향으로 이동”할지 전달하는 함수.

 

 

 


 

추천

 

[페이지] Unreal Engine | 언리얼 엔진

 

[Unreal Engine/UE 기초] - GameMode | [언리얼 엔진 C++ (Unreal Engine C++)]

 

GameMode | [언리얼 엔진 C++ (Unreal Engine C++)]

GameMode GameMode 이해하기 1️⃣ GameMode란?GameMode는 게임의 전반적인 규칙과 흐름을 총괄 관리하는, 일종의 컨트롤 타워 역할을 하는 클래스입니다.다른 곳에서 사용하는 GameManager 와 동일하다고 생

devcol.tistory.com

 

[Unreal Engine/UE 기초] - Character 클래스 구현 | [언리얼 엔진 C++ (Unreal Engine C++)]

 

Character 클래스 구현 | [언리얼 엔진 C++ (Unreal Engine C++)]

Character 클래스 구현 Pawn과 Character Class 정의 1️⃣ Pawn 클래스란?Pawn은 플레이어 혹은 AI가 “소유( Possess )”할 수 있는 가장 상위 클래스입니다. 즉, 엔진에서 “무언가를 조종한다”라고 할 때

devcol.tistory.com

 

[Unreal Engine/UE 기초] - Enhanced Input System 입력 매핑 구현하기 | [언리얼 엔진 C++ (Unreal Engine C++)]

 

Enhanced Input System 입력 매핑 구현하기 | [언리얼 엔진 C++ (Unreal Engine C++)]

Enhanced Input System 입력 매핑 구현하기 PlayerController, IMC, IA PlayerController 이해하기 1️⃣ PlayerController란?PlayerController는 사용자가 키보드, 마우스, 게임패드 등에서 입력을 받으면, 그 입력을 해석하

devcol.tistory.com

 

 

저작자표시 동일조건 (새창열림)
'Unreal Engine/UE 기초' 카테고리의 다른 글
  • 충돌 이벤트로 획득되는 아이템 구현하기 | [언리얼 엔진 C++ (Unreal Engine C++)]
  • 인터페이스 기반 아이템 클래스 설계하기 | [언리얼 엔진 C++ (Unreal Engine C++)]
  • 캐릭터 애니메이션 적용 | [언리얼 엔진 C++ (Unreal Engine C++)]
  • Enhanced Input System 입력 매핑 구현하기 | [언리얼 엔진 C++ (Unreal Engine C++)]
DevCol
DevCol
DevCol (Development Collaboration). 함께 개발 & 공부 & IT 정보 나눔장소
  • DevCol
    DevCol (Development Collaboration)
    DevCol
  • 블로그 메뉴

    • Unreal Engine
    • TIL
    • 게임국가기술자격검정 게임프로그래밍전문가 [한국콘텐츠진흥원]
    • 분류 전체보기 (73) N
      • Unreal Engine (31) N
        • Project (2) N
        • Dev Log (0)
        • Debugging (2) N
        • Blueprint (1)
        • UE 기초 (25) N
        • UE 심화 (0)
        • TA (1) N
      • Programming Language (0)
        • C++ (0)
        • C# (0)
      • Unity Engine (0)
      • 자격증 (3)
        • 게임국가기술자격검정 [한국콘텐츠진흥원] (3)
      • Coding Test | 코딩테스트 (0)
        • 프로그래머스 기초 (0)
        • 프로그래머스 입문 (0)
      • TIL (38) N
        • Boot Camp (32) N
      • Git & Github (1)
  • 링크

    • Youtube
    • GitHub
    • itch.io
    • Blog (En)
  • 공지사항

  • 인기 글

  • 태그

    코드 카타
    Game Dev
    Unreal engine
    Devlog
    언리얼 엔진
    게임개발
    내일배움캠프
    til
    Boot Camp
    게임 개발
    c
    C++
    UE
    프로그래밍
    Programming
    UE5
    Code Kata
    cpp
    기초
    코드카타
  • 최근 글

  • GitHub Youtube itch
  • hELLO · Designed By 정상우.v4.10.6
  • DevCol
    캐릭터 동작 구현과 입력 처리 | [언리얼 엔진 C++ (Unreal Engine C++)]
    상단으로

    티스토리툴바