캐릭터 동작 구현과 입력 처리
캐릭터 동작 구현과 입력 처리 관련 이전에 한 것들
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)에서 “어떤 함수가 호출될지”를 바인딩 (연결) 해주어야 최종적으로 동작이 이루어집니다.
- 정리하자면
- PlayerController는 MainInputMappingContext(IMC)를 활성화합니다.
- 해당 IMC에는 IA_Move, IA_Jump 등의 UInputAction들이 키보드/마우스와 맵핑되어 있습니다.
- 캐릭터가 SetupPlayerInputComponent() 함수를 통해 “각 액션이 발생했을 때 어떤 함수를 실행할지”를 등록해둡니다.
- 이렇게 등록한 함수들이, 실제로 움직이거나 점프하는 등 캐릭터 동작을 수행합니다.
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;로 연산할 수도 있습니다.
- 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
