본문 바로가기

언리얼 + cpp

언리얼C++ 5일차(액션 바인딩, 행동 함수 구현)

현재까지 게임모드를 만들고 게임모드로 캐릭터와 플레이어 컨트롤러를 관리했다.

플레이어 컨트롤러는 사용자의 입력과 캐릭터 사이를 연결해주고 IMC를 활성화 시켰다.

이제 어떤 키를 눌렀을 때 어떤 행동(함수)를 할것인지를 구현해야한다.

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

입력 액션을 처리할 함수를 선언한다.

인핸스드 인풋에서 입력 액션 값은 FInputActionValue로 전달된다.

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

	UFUNCTION()
	void Move(const FInputActionValue& value);
	UFUNCTION()
	void StartJump(const FInputActionValue& value);
	UFUNCTION()
	void StopJump(const FInputActionValue& value);
	UFUNCTION()
	void Look(const FInputActionValue& value);
	UFUNCTION()
	void StartSprint(const FInputActionValue& value);
	UFUNCTION()
	void StopSprint(const FInputActionValue& value);
매개변수를 const &로 받는 이유는 구조체의 경우 크기가 커서 그냥 값을 받을경우 복사되어 성능 저하 문제가 있다.
&(참조)로 원본을 가져오고 const로 값을 변경못하게 방어를 하는것이다.
// 캐릭터 소스

void AJinCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	if (UEnhancedInputComponent* EnhancedInput = Cast<UEnhancedInputComponent>(PlayerInputComponent))
	{
		if (AJinPlayerController* PlayerController = Cast<AJinPlayerController>(GetController()))
		{
			if (PlayerController->Move)
			{	// IA_Move 액션 키를 "누르고 있는 동안" Move 함수 호출
				EnhancedInput->BindAction(PlayerController->Move, ETriggerEvent::Triggered, this, &AJinCharacter::Move);
			}

			if (PlayerController->Jump)
			{	// IA_Jump 액션 키를 "누르고 있는 동안" StartJump 함수 호출
				EnhancedInput->BindAction(PlayerController->Jump, ETriggerEvent::Triggered, this, &AJinCharacter::StartJump);
				// IA_Jump 액션 키를 "뗀 순간" StopJump 함수 호출
                		EnhancedInput->BindAction(PlayerController->Jump, ETriggerEvent::Completed, this, &AJinCharacter::StopJump);
			}

			if (PlayerController->Look) //
			{	// IA_Look 액션 마우스가 "움직이는 동안" Jump 함수 호출
				EnhancedInput->BindAction(PlayerController->Look, ETriggerEvent::Triggered, this, &AJinCharacter::Look);
			}

			if (PlayerController->Sprint)
			{	// IA_Sprint 액션 키를 "누르고 있는 동안" StartSprint 함수 호출
				EnhancedInput->BindAction(PlayerController->Sprint, ETriggerEvent::Triggered, this, &AJinCharacter::StartSprint);
				// IA_Sprint 액션 키를 "뗀 순간" StopSprint 함수 호출
                		EnhancedInput->BindAction(PlayerController->Sprint, ETriggerEvent::Completed, this, &AJinCharacter::StopSprint);
			}
		}
	}
}

if (UEnhancedInputComponent* EnhancedInput = Cast<UEnhancedInputComponent>(PlayerInputComponent))

-> Enhanced InputComponent로 캐스팅

if (AJinPlayerController* PlayerController = Cast<AJinPlayerController>(GetController()))

-> IA를 가져오기 위해 현재 소유 중인 Controller를 AJinPlayerController로 캐스팅

// 캐릭터 소스
// BineAction 함수에서 인자로 넣은 함수들(실제로 행동 로직을 구현할 함수)

void AJinCharacter::Move(const FInputActionValue& value)
{
}

void AJinCharacter::StartJump(const FInputActionValue& value)
{
}

void AJinCharacter::StopJump(const FInputActionValue& value)
{
}

void AJinCharacter::Look(const FInputActionValue& value)
{
}

void AJinCharacter::StartSprint(const FInputActionValue& value)
{
}

void AJinCharacter::StopSprint(const FInputActionValue& value)
{
}
  • FInputActionValue: Enhanced Input에서 액션 값 (축 이동값, 마우스 이동량 등)을 전달할 때 사용하는 구조체로, IA에서 설정한 Value Type입니다.
  • UFUNCTION(): 입력 바인딩 함수는 언리얼 엔진 리플렉션 시스템과 연동되어야 합니다. UFUNCTION()을 붙이지 않으면 바인딩에 실패할 수 있습니다.
    • 블루프린트 접근성을 설정하지 않았더라도, 기본적으로 메타데이터가 생성됩니다.
    • 언리얼 엔진의 입력 처리 시스템은 바인딩된 함수가 리플렉션 시스템을 통해 접근 가능한지 확인합니다.
  • BindAction 함수
    • 첫 번째 인자: 어떤 UInputAction과 연결할지. (예: MoveAction)
    • 두 번째 인자: 액션이 발생하는 트리거 이벤트 (Triggered, Ongoing, Completed 등).
    • 세 번째/네 번째 인자: 액션 발생 시 실행할 객체(this)와 함수 포인터.
  • 점프와 스프린트 함수 분리
    • IA에서 설정한 Value Type이 bool일 경우 "키를 누를 때"와 "뗄 때"가 다르게 처리되도록 보통 두 함수로 분리한다.

행동 함수 구현하기

Move

void AJinCharacter::Move(const FInputActionValue& value)
{
	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);
	}
}

value는 Axis2D로 설정된 IA_Move의 입력값 (WASD)을 담고 있음, if 조건은 오류를 방지하기 위한 방어 코드

  • AddMovementInput(방향, 크기)
    • 첫 번째 파라미터: 월드 좌표 기준 이동 방향(Forward, Right 등)
    • 두 번째 파라미터: 이동 스케일(속도)
    • 내부적으로 CharacterMovementComponent가 이 요청을 받아 속도를 계산하고, 실제 이동을 구현합니다.

Jump

void AJinCharacter::StartJump(const FInputActionValue& value)
{
	if (value.Get<bool>())
	{
		Jump();
	}
}

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

Look

void AJinCharacter::Look(const FInputActionValue& value)
{
	FVector2D LookInput = value.Get<FVector2D>();
	AddControllerYawInput(LookInput.X);
	AddControllerPitchInput(LookInput.Y);
}
  • AddControllerYawInput(): 카메라의 Yaw 축 (수평 회전)을 변경
  • AddControllerPitchInput(): 카메라의 Pitch 축 (수직 회전)을 변경
  • 실제 어느 방향으로 얼마나 회전할지는, 프로젝트 세팅InputMouse SensitivityLookInput에 곱해줄 스케일 (Modifiers)을 통해 조정할 수 있습니다.

Sprint

우선, 캐릭터 클래스 SpartaCharacter.h 파일에서 스프린트 관련 멤버 변수를 추가해야 합니다.

// 캐릭터 헤더
private:
	float NormalSpeed;
	float SprintSpeedMultiplier;
	float SprintSpeed;

언리얼 엔진의 CharacterMovementComponent에는 MaxWalkSpeed라는 속성이 있습니다.

MaxWalkSpeed 값을 변경하면, 캐릭터의 이동 속도가 즉시 바뀝니다.

생성자에서 변수의 기초 값들을 넣어주고 MaxWalkSpeed를 NormalSpeed 값을 넣어준다.

// 캐릭터 소스
	NormalSpeed = 600.0f;
	SprintSpeedMultiplier = 1.7f;
	SprintSpeed = NormalSpeed * SprintSpeedMultiplier;

	GetCharacterMovement()->MaxWalkSpeed = NormalSpeed;

GetCharacterMovement() : ACharacter 클래스에 기본 내장된 함수로, UCharacterMovementComponent* 포인터를 반환합니다. 여기서 MaxWalkSpeed 등의 이동 관련 설정을 바꿀 수 있습니다.

void AJinCharacter::StartSprint(const FInputActionValue& value)
{
	if (GetCharacterMovement())
	{
		GetCharacterMovement()->MaxWalkSpeed = SprintSpeed;
	}
}

void AJinCharacter::StopSprint(const FInputActionValue& value)
{
	if (GetCharacterMovement())
	{
		GetCharacterMovement()->MaxWalkSpeed = NormalSpeed;
	}
}

value값이 true면 MaxWalkSpeed를 SprintSpeed로, false면 NormalSpeed로 설정한다.