ThirdPersonCharacter와EnhancedInput (2)

YH J·2023년 12월 11일
0

UE5 C++

목록 보기
7/10

삼인칭으로 프로젝트를 만들면 생성되는 ThirdPersonCharacter와 Enhanced Input으로 구현되어있는 입력 분석하기

1. InputAction을 추가하는 이유

우리는 이미 InputMappingContext(IMC)에 InputAction들을 추가해서 매핑해두었다.
캐릭터 C++에서 IMC를 추가하고 BeginPlay에서UEnhancedInputLocalPlayerSubsystem에 AddMappingContext로 IMC를 추가해주면 끝인거같지만 따로 InputAction들도 변수화하고 넣어주어야한다.

IMC에 InputAction을 추가한 후에도 문자에 InputAction을 별도로 추가해야 하는 이유는 Unreal Engine에서 입력 처리를 설계하는 방식 때문이다. IMC에 InputAction을 추가하는것은 특정 컨텍스트나 상황에서 이 작업이 유효함을 지정하는 것이다. 그러나 이 작업이 자동으로 캐릭터의 함수와 바인드 되지는 않으므로 캐릭터에 InputAction을 추가하고 함수를 바인드해주어야 한다.

2. AddMappingContext

//Add Input Mapping Context
void AThirdPersonCharacter::BeginPlay()
{
	Super::BeginPlay();

	if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
	{
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
		{
			Subsystem->AddMappingContext(DefaultMappingContext, 0);
		}
	}
}

플레이어 컨트롤러에서 로컬플레이어(클라이언트에서 플레이되는 매인 플레이어)의 SubSystem을 가져와서 AddMappingContext로 추가해준다.
여러개의 IMC를 추가할 수 있고, 뒤의 숫자는 우선순위이며 숫자가 높을수록 우선순위가 높다.
이 우선순위 설정을 통해 입력소모로 하나의 키로 여러 동작을 구현 할 수 있다.

3. SetupPlayerInputComponent

void AThirdPersonCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent)) 
    {
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACharacter::Jump);
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &APlayerBase::Move);
		EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &APlayerBase::Look);
	}
}

언리얼4때 바인딩하던것과 유사한 구조이다.EnhancedInput은 UEnhancedInputComponent의 BindAction을 사용하는데 원하는 InputAction에 ETriggerEvent를 설정하고, 오브젝트(this)와 함수의 포인터이다.
ETriggerEvent의 종류는 None, Triggered, Started, Ongoing, Canceled, Completed가 있다.

  • None : 중요한 트리거 상태 변경이 발생하지 않았으며 활성 장치 입력이 없음을 나타낸다. 이 상태는 작업이 트리거되지 않음을 의미한다.
  • Triggered : 이 상태는 트리거 평가가 시작된 이벤트가 발생했음을 의미한다. Started 이벤트는 Triggered이벤트와 동일한 프레임에서 발생할 수도 있지만 항상 Started가 먼저 시작된다.
  • Started : 이 이벤트는 트리거 평가가 시작되면 시작된다. 즉, 액션 트리거의 시작이다.
  • Ongoing : 이 상태는 트리거가 아직 평가 중임을 의미한다. 작업의 트리거가 여전히 발생하고 있음을 나타내는 데 사용된다.
  • Canceled : 이 상태는 트리거 평가가 취소되었을 때 사용된다. 이는 작업의 트리거가 완료되기 전에 중지되었음을 의미한다.
  • Completed : 이 상태는 이 프레임에서 Triggered 상태가 에서 None 으로 전환되었음을 나타낸다. 즉, 트리거 평가가 완료되었음을 의미한다.

4. 입력 처리 과정

개인적으로 정리한 입력처리 과정

키 입력 -> 우선순위가 높은 InputMappingContext부터 해당 키가 매핑되어있는지 검사 -> 매핑되어 있는 InputAction이 있다면 해당 InputAction에 바인딩 되어 있는 함수 실행

개인적으로 찾아본 궁금한것

  • BindAction때 InputMappingContext에 대한것은 찾아볼 수 없는데 여러개의 IMC을 추가하면 어떻게 구분되는가?
    = 이건 위의 입력처리 과정에 대해 정리하면서 해결되었다. 그냥 InputAction에 함수를 바인딩하고 해당 InputAction이 IMC에 매핑되어있으면 작동하는것이므로 구분 할 필요가 없다.
  • 여러개의 IMC에 하나의 InputAction을 매핑해두고 이 InputAction에 IMC마다 작동하고 싶은 함수를 여러개 바인딩 해두면 키 입력시 우선순위에 따라 작동하는가?
    = 애초에 BindAction시 IMC를 구분 할 수 없으므로 그냥 잘못된 설계이다. 이렇게 만들면 그냥 키 입력시 InputAction에 바인딩 된 모든 함수가 실행 될 것이다.
    여러개의 IMC와 하나의 키로 동작을 구분하고 싶다면 IMC마다 다른 InputAction을 만들고 각각의 InputAction마다 함수를 바인딩하되 매핑을 같은 키로 하고 우선순위를 잘 설정해주면 될 것이다.
profile
게임 개발자 지망생

0개의 댓글