ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [UE5] Enhanced Input Binding with Gameplay Tags C++
    언리얼엔진/그 외 2024. 1. 21. 16:58

     

    원문: 

    https://dev.epicgames.com/community/learning/tutorials/aqrD/unreal-engine-enhanced-input-binding-with-gameplay-tags-c

     

    Enhanced Input Binding with Gameplay Tags C++ | Tutorial

    This tutorial covers setting up a foundational Enhanced Input system in the First Person Template. This a minimalized version of the system implemented ...

    dev.epicgames.com

     

    1인칭 템플릿을 이용해서 Enhanced Input Binding과 게임플레이 태그를 사용하는 예제다.

    이 글은 위의 내용을 한번 정리하는 내용이다.

     

     

     


     

     

     

    Pawn은 SetupPlayerInputComponent 함수에서 입력 바인딩 작업을 진행한다.

    일반적인 방식으로는 EnhancedInputComponent에 입력 액션을 지정해서 바인딩을 하는데 이 예제에서는 게임플레이 태그를 지정하면 그에 맞는 입력 액션을 찾아서 바인딩 해준다.

    그러기 위해선 게임플레이 태그에 새로운 태그를 추가해야하고, 그 태그와 입력 에셋을 연결해놓은 데이터 에셋이 필요하다.

    이 데이터 에셋에서 게임플레이 태그 와 입력 액션을 미리 묶어두고, 캐릭터에서는 이 데이터 에셋을 활용해서 게임플레이 태그를 통해 입력 액션을 찾아서 바인딩 한다.

     


     

    1인칭 템플릿의 BP_FirstPersonCharacter는 입력 액션을 아래와 같이 지정해뒀다.

     

    참고로 DefaultMappingContext는 None인데 원래 여기에 지정되어야할 입력 매핑 컨텍스트는 플레이어 컨트롤러에서 추가하게 되어있으므로 캐릭터에서는 추가할 필요가 없다.

    아무튼 기존에는 이렇게 입력 액션을 하나씩 지정해줘서 캐릭터의 SetupPlayerInputComponent 함수에서 함수를 바인딩 한다.

    void AMyProjectCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
        // Set up action bindings
        if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent))
        {
            // Jumping
            EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
            EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
    
            // Moving
            EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Move);
    
            // Looking
            EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Look);
        }
        else
        {
            UE_LOG(LogTemplateCharacter, Error, TEXT("'%s' Failed to find an Enhanced Input Component! This template is built to use the Enhanced Input system. If you intend to use the legacy system, then you will need to update this C++ file."), *GetNameSafe(this));
        }
    }

     

    이런식으로 입력 에셋을 하나씩 지정하는 대신에 예제에서 만들게 될 InputConfig 데이터 에셋을 지정해주고, 이 데이터 에셋에서 게임플레이 태그에 맞는 입력 액선을 찾아서 바인딩 하는 것이 예제의 목적이다.

     

    InputConfig에 입력 액션과 게임플레이 태그가 묶여있다.

     

    그래서 아래와 같이 입력 바인딩을 하게 된다.

    void AMyProjectCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
        UMyEnhancedInputComponent* MyEnhancedInputComponent = Cast<UMyEnhancedInputComponent>(PlayerInputComponent);
    
        // Make sure to set your input component class in the InputSettings->DefaultClass;
        check(MyEnhancedInputComponent);
    
        const FMyGameplayTags& GameplayTags = FMyGameplayTags::Get();
    
        // Bind Input actions by tag
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Move, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Input_Move);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Look_Mouse, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Input_Look);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Look_Stick, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Input_Look);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Jump, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Input_Jump);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Fire, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Input_Fire);
    }

     


     

    이 예제에서는 게임플레이 태그를 C++와 언리얼 에디터에서 사용하기 위해 게임플레이 태그를 C++에서 native하게 정의하고, 싱글톤 전역 구조체에서 관리해서 어디에서든 접근 가능하게 했다.

    그리고 에디터를 로드할때 같이 로드되게 하기 위해서 에셋 매니저를 상속받아서 StartInitialLoading 함수에서 UGameplayTagsManager에 네이티브 게임플레이 태그를 추가하는 과정을 진행한다.

    이렇게 생성한 에셋 매니저를 에디터의 프로젝트 세팅 → 엔진 → 일반 세팅 → Default Classes → 고급 → 에셋 매니저 클래스에 지정해줘야 한다.

     

    에디터를 다시 시작하면 프로젝트 세팅 → GameplayTags → 게임플레이 테그 목록에 아래와 같이 네이티브 게임플레이 태그가 추가된걸 확인할 수 있다.

     

     

    이제 에디터에서도 이 태그들을 사용할 수 있다.

     


     

    참고로 이 방법 말고 NativeGameplayTags.h 헤더 파일에 있는 매크로를 사용하면 위와 같이 싱글톤 구조체를 생성하지 않아도 네이티브 게임플레이 태그를 추가할 수 있다.

    // .h
    #include "NativeGameplayTags.h"
    
    UE_DECLARE_GAMEPLAY_TAG_EXTERN(Tag_Example_1); // 태그 선언
    UE_DECLARE_GAMEPLAY_TAG_EXTERN(Tag_Example_2);
    
    
    
    // .cpp
    UE_DEFINE_GAMEPLAY_TAG(Tag_Example_1, "Tag.Example.1"); // 태그 정의
    UE_DEFINE_GAMEPLAY_TAG_COMMENT(Tag_Example_2, "Tag.Example.2", "Tag Comment");

    다른곳에서 이 태그가 선언된 헤더 파일을 include하면 네이티브 게임플레이 태그를 사용할 수 있다.

    UE_DEFINE_GAMEPLAY_TAG_STATIC 매크로도 존재하는데 이 경우에는 따로 선언할 필요없이 이 매크로로 정의만 하면 태그를 사용할 수 있지만, 태그를 정의한 파일에서만 사용 가능하다.

     

     

     


     

     

     

    게임플레이 태그는 상태를 나타낼때도 많이 사용되는데 이 예제를 조금 응용해서 UI에 입력 상태를 표시하게 해봤다.

    캐릭터에 게임플레이 태그 컨테이너를 추가해서 태그를 저장할 수 있게 하고 입력 바인딩에 ETriggerEvent::Completed인 경우에도 함수를 연결해서 블루프린트에서 상속받아 구현할 수 있게 했다.

    void AMyProjectCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
        UMyEnhancedInputComponent* MyEnhancedInputComponent = Cast<UMyEnhancedInputComponent>(PlayerInputComponent);
    
        // Make sure to set your input component class in the InputSettings->DefaultClass;
        check(MyEnhancedInputComponent);
    
        const FMyGameplayTags& GameplayTags = FMyGameplayTags::Get();
    
        // Bind Input actions by tag
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Move, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Input_Move);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Look_Mouse, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Input_Look);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Look_Stick, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Input_Look);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Jump, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Input_Jump);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Fire, ETriggerEvent::Triggered, this, &AInputBindingCharacter::Input_Fire);
    
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Move, ETriggerEvent::Completed, this, &AInputBindingCharacter::Input_Move_Complete);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Look_Mouse, ETriggerEvent::Completed, this, &AInputBindingCharacter::Input_Look_Complete);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Look_Stick, ETriggerEvent::Completed, this, &AInputBindingCharacter::Input_Look_Complete);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Jump, ETriggerEvent::Completed, this, &AInputBindingCharacter::Input_Jump_Complete);
        MyEnhancedInputComponent->BindActionByTag(InputConfig, GameplayTags.InputTag_Fire, ETriggerEvent::Completed, this, &AInputBindingCharacter::Input_Fire_Complete);
    }

     

     

     

    게임플레이 태그를 사용하면 다양한 상태를 bool 변수나 맵 또는 배열을 사용하지 않아도 쉽게 저장하고 다룰 수 있다는 장점이 있다.

    프로젝트를 진행하다보면 다양한 상태에 따라 다른 동작이 필요한 경우가 많아서 변수가 계속 증가하는 불편함이 있는데 이때 유용하게 사용될 수 있다.

     

     

Designed by Tistory.