📌입력 바인딩 함수를 Enhanced Input System에서 인식하려면 리플렉션 시스템에 등록해야 한다.
// 헤더
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "CH3_Character.generated.h"
// 미리 선언
// 여기서 사용하지 않는데 헤더를 포함시키면 볼륨이 쓸데없이 커지니까
// 선언만해서 있다고 알려만 주고 헤더는 cpp에서 선언
class USpringArmComponent;
class UCameraComponent;
struct FInputActionValue;
UCLASS()
class CH3_PROJECT_API ACH3_Character : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
ACH3_Character();
// VisibleAnywhere, BlueprintReadOnly: 객체 자체를 변경하는 건 불가능하지만 내부 속성 정도는 수정 가능
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
USpringArmComponent* SpringArmComp;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
UCameraComponent* CameraComp;
protected:
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
// 입력 바인딩 함수는 리플렉션 시스템과 연동이 되어야함
// 등록 되어있지 않으면 Enhanced Input System에서 인식을 못함
UFUNCTION()
// FInputActionValue: IA의 Value Type
void Move(const FInputActionValue& Value);
UFUNCTION()
void Look(const FInputActionValue& Value);
// 입력이 on/off인 동작들은 시작과 끝을 나눠주는게 좋음
UFUNCTION()
void StartJump(const FInputActionValue& Value);
UFUNCTION()
void StopJump(const FInputActionValue& Value);
UFUNCTION()
void StartSprint(const FInputActionValue& Value);
UFUNCTION()
void StopSprint(const FInputActionValue& Value);
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speed")
float SprintSpeedMultiplier;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MouseSensitivity")
float MouseSensitivity;
private:
float NormalSpeed;
float SprintSpeed;
int JumpCount = 0;
};
// cpp
// Called to bind functionality to input
void ACH3_Character::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
if (UEnhancedInputComponent* EnhancedInput =
Cast<UEnhancedInputComponent>(PlayerInputComponent))
{
// 현재 캐릭터를 조작하는 컨트롤러를 가져와 ACH3_PlayerController로 캐스팅
if (ACH3_PlayerController* PlayerController =
Cast<ACH3_PlayerController>(GetController()))
{
if (PlayerController->MoveAction)
{
// 이벤트랑 함수 연결
EnhancedInput->BindAction(
PlayerController->MoveAction,
ETriggerEvent::Triggered,
this,
&ACH3_Character::Move
);
}
if (PlayerController->LookAction)
{
// 이벤트랑 함수 연결
EnhancedInput->BindAction(
PlayerController->LookAction,
ETriggerEvent::Triggered,
this,
&ACH3_Character::Look
);
}
if (PlayerController->JumpAction)
{
// 이벤트랑 함수 연결
EnhancedInput->BindAction(
PlayerController->JumpAction,
ETriggerEvent::Triggered,
this,
&ACH3_Character::StartJump
);
EnhancedInput->BindAction(
PlayerController->JumpAction,
ETriggerEvent::Completed,
this,
&ACH3_Character::StopJump
);
}
if (PlayerController->SprintAction)
{
// 이벤트랑 함수 연결
EnhancedInput->BindAction(
PlayerController->SprintAction,
ETriggerEvent::Triggered,
this,
&ACH3_Character::StartSprint
);
EnhancedInput->BindAction(
PlayerController->SprintAction,
ETriggerEvent::Completed,
this,
&ACH3_Character::StopSprint
);
}
}
}
}
void ACH3_Character::Move(const FInputActionValue& Value)
{
// 컨트롤러 유효한지 확인
// GetActorForwardVector 같은 값은 컨트롤러 없으면 못가져옴
if (!Controller) return;
const FVector2D MoveInput = Value.Get<FVector2D>();
if (!FMath::IsNearlyZero(MoveInput.X))
{
AddMovementInput(GetActorForwardVector(), MoveInput.X);
}
if (!FMath::IsNearlyZero(MoveInput.Y))
{
AddMovementInput(GetActorRightVector(), MoveInput.Y);
}
}
void ACH3_Character::Look(const FInputActionValue& Value)
{
FVector2D LookInput = Value.Get<FVector2D>();
// 좌우 회전
// 값이 양수면 오른쪽으로 회전
AddControllerYawInput(LookInput.X * MouseSensitivity);
// 상하 회전
// 값이 양수면 아래로 회전
// IMC에서 이미 값을 반전시켜서 여기서는 신경 X
AddControllerPitchInput(LookInput.Y * MouseSensitivity);
}
void ACH3_Character::StartJump(const FInputActionValue& Value)
{
// Jump 함수에 컨트롤러 체크가 이미 있고
// 컨트롤러가 필요한 함수도 없어서 체크 안해도 됨
//if (!Controller) return;
if (Value.Get<bool>())
{
Jump();
}
}
void ACH3_Character::StopJump(const FInputActionValue& Value)
{
if (!Value.Get<bool>())
{
StopJumping();
JumpCount++;
UE_LOG(LogTemp, Display, TEXT("Jump Count: %d"), JumpCount);
}
}
void ACH3_Character::StartSprint(const FInputActionValue& Value)
{
if (GetCharacterMovement())
{
SprintSpeed = NormalSpeed * SprintSpeedMultiplier;
GetCharacterMovement()->MaxWalkSpeed = SprintSpeed;
}
}
void ACH3_Character::StopSprint(const FInputActionValue& Value)
{
if (GetCharacterMovement())
{
UE_LOG(LogTemp, Warning, TEXT("SprintSpeed: %0.1f"), SprintSpeed);
GetCharacterMovement()->MaxWalkSpeed = NormalSpeed;
}
}
출처: 스파르타코딩 내일배움캠프