[UE5] #2 - Player-2 | Enhanced Input

qweasfjbv·2024년 9월 20일

UnrealEngine5

목록 보기
2/8

개요


언리얼 엔진에서 GameplayTag 로 Enhanced Input을 사용하기 위해서는 준비해야할 것들이 많습니다.

  1. 만들 기능의 GameplayTag, Input Action 설정
  2. Input Mapping Context에 IA와 키보드(혹은 게임패드) 입력 Mapping
  3. EnhancedInputLocalPlayerSubsystem에 MappingContext 를 Add
  4. EnhancedInputComponent 에서 IA와 InputFunction을 Bind

이렇게 하면 키보드 입력->(Mapping Context)->InputAction->InputFunction 처럼 흘러가게 됩니다.
우선 GameplayTag 부터 차근차근 만들어보겠습니다.

구현


GameplayTag 설정

	/** On Header File **/
	~_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_Move);
	~_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_Look);

	/** On cpp File **/
	UE_DEFINE_GAMEPLAY_TAG(InputTag_Move, "InputTag.Move");
	UE_DEFINE_GAMEPLAY_TAG(InputTag_Look, "InputTag.Look");

위와 같이 태그를 선언해줍니다.
여기서 선언한 태그들은 Edit->ProjectSetting->GameplayTags->게임플레이 태그 관리 에서 확인하실 수 있습니다.

Build.cs 파일의 PublicDependencyModuleNames.AddRange 부분에 EnhancedInput, GameplayTags가 포함되어 있는지 확인해야합니다.


Input Action 설정

프로젝트를 처음만들면 주어지는 IA_Move, IA_Look을 그대로 사용하셔도 좋습니다.
만약 없다면, 콘텐츠 드로어에서 마우스 우클릭 -> 입력 -> 입력 액션 으로 IA를 만드신 후에, 값 타입을 Axis2D 로 바꿔주시면 됩니다.
Move와 Look 모두 상하좌우를 이동해야하기 때문에 필요합니다.

IA를 만들고 MappingContext에 등록해줍니다.


EnhancedInputSubsystem에 AddMappingContext

/** Header File **/
protected:
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    
private:
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CharacterData", meta = (AllowPrivateAccess = "true"))
	UDataAsset_InputConfig* InputConfigDataAsset;

/** PlayerBaseCharacter::SetupPlayerInputComponent **/

	ULocalPlayer* LocalPlayer = GetController<APlayerController>()->GetLocalPlayer();

	UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(LocalPlayer);
	check(Subsystem);

	Subsystem->AddMappingContext(InputConfigDataAsset->DefaultMappingContext, 0);
    
	UPlayerInputComponent* LocalInputComponent = CastChecked<UPlayerInputComponent>(PlayerInputComponent);
	LocalInputComponent->BindNativeInputAction(InputConfigDataAsset, PlayerGameplayTags::InputTag_Move, ETriggerEvent::Triggered, this, &ThisClass::Input_Move);
	LocalInputComponent->BindNativeInputAction(InputConfigDataAsset, PlayerGameplayTags::InputTag_Look, ETriggerEvent::Triggered, this, &ThisClass::Input_Look);

EnhancedLocalPlayerInputSubsystem에 접근하여 AddMappingContext를 호출합니다.

여기서 보지못했던 InputConfigDataAssetUPlayerInputComponent 가 나옵니다.
해당 클래스는 직접 만들어야 합니다.

UDataAsset_InputConfig : UDataAsset

/** HeaderFile **/
public:
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UInputMappingContext* DefaultMappingContext;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (TitleProperty="InputTag"))
	TArray<FPlayerInputActionConfig> NativeInputActions;

	UInputAction* FindNativeInputActionByTag(const FGameplayTag& InInputTag) const;

DefaultMappingContext : 시작할 때 등록할 MappingContext
NativeInputActions : 시작할 때 등록할 IAs
FPlyaerInputActionConfig : GameplayTag와 InputAction이 포함된 구조체
FindNative~ByTag : 위 배열을 돌며 Tag와 일치하는 IA 반환

PlayerInputComponent : UEnhancedInputComponent

/** HeaderFile **/

template<class UserObject, typename CallbackFunc>
inline void UPlayerInputComponent::BindNativeInputAction(const UDataAsset_InputConfig* InInputConfig, const FGameplayTag& InInputTag, ETriggerEvent TriggerEvent, UserObject* ContextObject, CallbackFunc Func)
{
	check(InInputConfig);

	if (UInputAction* FoundAction = InInputConfig->FindNativeInputActionByTag(InInputTag)) {
		BindAction(FoundAction, TriggerEvent, ContextObject, Func);
	}
}

여기에 입력받는 Func 는 함수를 호출하는 부분에서 구현하여 인자로 넘겨줍니다.
Move, Look 의 경우, 해당 함수의 파라미터로 FInputActionValue 를 받을 수 있으며, IA에서 Axis2D로 설정했으므로 Get<FVector2D>() 를 통해 입력값을 받아 처리할 수 있습니다.

해당 InputComponent 를 사용하려면 ProjectSetting 에서 설정해주어야합니다.

Input_Move, Input_Look

void APlayerBaseCharacter::Input_Move(const FInputActionValue& InputActionValue)
{
	const FVector2D MovementVector = InputActionValue.Get<FVector2D>();
	const FRotator MovementRotation(0.f, Controller->GetControlRotation().Yaw, 0.f);

	if (MovementVector.Y != 0.f) {
		const FVector ForwardDirection = MovementRotation.RotateVector(FVector::ForwardVector);

		AddMovementInput(ForwardDirection, MovementVector.Y);
	}
	if (MovementVector.X != 0.f) {
		const FVector RightDirection = MovementRotation.RotateVector(FVector::RightVector);

		AddMovementInput(RightDirection, MovementVector.X);
	}
}


void APlayerBaseCharacter::Input_Look(const FInputActionValue& InputActionValue)
{
	const FVector2D LookAxisVector = InputActionValue.Get<FVector2D>();

	if (LookAxisVector.X != 0.f) {
		AddControllerYawInput(LookAxisVector.X);
	}

	if (LookAxisVector.Y != 0.f) {
		AddControllerPitchInput(LookAxisVector.Y);
	}

}

예를 들어, Input_Move 는 InputActionValue에서 화살표 입력을 FVector2D로 받습니다.
해당 입력은 상하좌우를 나타내며, AddMovementInput 함수로 움직임을 구현합니다.


여기까지 구현한 후에 전부 에셋으로 만든 후에 하나씩 설정합니다.

전부 설정해주면 캐릭터가 움직이는 모습을 확인하실 수 있습니다.

마무리


Enhanced Input Component와 GameplayTags를 활용하여 캐릭터가 입력을 통해 움직일수 있도록 구현했습니다.
다음에는 움직임에 따라 캐릭터가 자연스럽게 움직일 수 있도록 애니메이션을 추가해보겠습니다.

0개의 댓글