2026.01.15

박민재 (Daype)·2026년 1월 15일

언리얼 엔진에서 제공하는 PlayerController 이용하여 캐릭터의 IMC 상태변화주기

구현목표 : 새로운 IMC를 만들어서 평상시에는 IMC_Character 인벤토리를 열경우 IMC_Character 가 삭제되고 IMC_Inven 이 할당되는 구조 만들어보기,

학습내용 : 언리얼 엔진에는 캐릭터의 움직임의 입력값만을 다루는 PlayerController 이 존재한다 또한 EnhancedInputSystem 이 존재하는데 EnhancedInputSystem 은 향상된 인풋 시스템으로 IMCIA 를 이용해 (InputMappingContext, InputAction) IA 에 등록한 캐릭터의 키값을 IMC 에 등록하여 종합적으로 관리하는 시스템이다. 이러한 구조로 이루어진 인풋시스템을 사용하게되면 예를들어서 플레이어는 걷다가 자동차를 타게되면 자동차의 조종을 해야하고 배를타면 배를 비행기를 타면 비행기를 조종해야하는데 IMC 를 이용해 배IMC 비행기IMC 를 구현해놓고 조건에 맞을경우 갈아 끼워주기만 하면 된다. 이렇게하면 매번 이동 관련된 함수와 로직을 변경할 필요없다. 덤으로 IA 에 내가 원하는 모든 움직임에 형태가 설정이되어있기때문에 움직임을 변경할땐 또 IA만 수정하면되는 굉장한 분할성을 보여준다.

학습내용을 바탕으로 IMC_Inven 과 IMC_Character를 분리하려한다.

세부구현 내용

  • PlayerController 클래스에서 IMC변수와 IA변수를 만들어서 할당한 후 BeginPlay() 가 호출될때 IMC_Character를 할당해주는 형식으로 구현되어있다.

  • IMC_Inven 과 Inven 에서 작동할 IA_UseItem 을 새로 만들어 초기화 해준다.

  • 변수를 만들고 생각을 해보니 IMC가 교체가 되려면 특정키를 눌러서 동작하게 만들어야한다는 생각이들었다. ex) I키를 누르면 인벤토리가 켜졌다 꺼졌다 하는 것

  • 이 상태에서 한참을 고민하다가 IMC를 새로만든다음 boolean변수를 하나 만들어서 boolean 변수가 바뀔때마다 IMC가 바뀌는 구조로 만들어야한다고 생각을 했다.

  • 그리고 boolean 변수를 동작으로 바꾸려면 동작을 바꾸는 함수가 필요하다는 것을 깨달았다.

  • 해당 상태의 로직을 구현한 후 Tick 함수를 만들어서 Tick함수내부에서 계속 호출하게 할경우 Bool 값이 바뀌면 저절로 재할당이 될거라고 생각을 했다.

  • Tick함수에서 호출하게해주었는데 언리얼엔진을 키고 테스트를 실행해본결과 아무일도 일어나지 않았고 블루프린트에 이벤트를 등록해서 Printstring은 제대로 동작하는것을 확인할 수 있었다.

  • 굉장히 오랜시간동안 고민 후 찾아본 결과 내가 지금까지 해준작업은 단지 IMC를 만들어서 IA를 할당해준 작업이었을뿐이다 해당 클래스를 파생시켜 블루프린트로 만들어서 EventAction 을 추가해줬다고 해도 해당키가 동작을 했나 안했나로 PrintString이 동작을 하는 구조였던것이다. 결과적으로 지금 구현해놓은 IMC들을 직접 캐릭터에게 바인딩을 해주어야 직접적으로 값을 가져와서 판별하고 호출될 동작에 맞는 함수또한 바인딩을해주어야 내가 원하는 동작을 가져올 수 있었던 것이다.

  • PlayerCharacter 클래스에는 언리얼에서 기본적으로 제공하는 이동 로직이 담긴 SetupPlayerInputComponent라는게 존재 한다는것을 알았다. 플레이어캐릭터가 가진 해당 함수에 내가 등록해놓은 IMC 들을 직접적으로 추가해서 바인딩을 해주어야 내가원했던 동작들이 가능하다는것이다. 해당내용을 공부한 후 방금 구현하려했던것을 다시 도전했다.

  • 본격적인 값을가져오고 동작을 구현하기위해서는 FInputActionValue 라는 구조체가 필요한데 사용하기위해 클래스 앞에 전방선언을 해주었고 구조체 같은경우는 데이터가 굉장히 크기때문에 &연산자를 사용에 참조해주었으며 구조체 값이 변경되면 안되기때문에 const 처리를 해주었다.

  • 이후 SetupPlayerInputComponent 함수 내부에서 EnhancedInputSystem 을 사용하기위해 캐스팅을 해주었고 마찬가지로 플레이어 컨트롤러 또한 캐스팅을 해주었다 캐스팅을 하는 이유는 변수에 보다 안전하게 접근하기위해서인데 포인터주소로 접근을 할 경우 문제가 생길 수 있다. 이후 캐스팅 조건문을 통과하게 되면 컨트롤러에 직접 구현해놓은 IA를 직접 호출하여 키를 바인딩해주고 해당키가동작하면 실행될 함수를 콜백해준다
    해당과정은 BindAction 함수를 통해 이루어지는데 인자값으로 가져올IA IA가 발생시키는 이벤트 동작, 함수를 실행할 객체, 동작할 함수 를 등록한다. 이렇게해놓으면 키입력으로 동작을 할때마다 해당함수가 콜백되어 실행된다.
    이 개념을 이용해 기본적으로 구현한 이동 점프 Look 말고도 아까 구현하려고했던 IMC분리 기능또한 구현이 가능하다.

  • 인벤토리에서 동작을 확인할 UseItem 과 인벤토리를 여는 OpenInven 함수를 만들어준다

  • 동일하게 bindAction 으로 등록을한다.

  • 지금 구현하려는것은 언리얼 엔진에서 제공하는 기능이 아니라 직접 만들어서 구현할 기능들이기 때문에 일단 UseItem 에는 아이템 사용을 알리는 문구를 출력하게 해주었고 OpenInven에선 PlayerController 에 구현해놓은 컨트롤러 교체함수를 직접 호출해주어야하기때문에 다시한번 이 함수내에서 컨트롤러를 직접 캐스팅한다음 함수를 호출해주었다.

  • 최종적으로 플레이스타트 버튼을 누르게되면 IMC_Common 상태가 기본으로 되고 이상태에서 I인벤토리 열기 키를 누르게되면 조건문이 true가 되면서 인벤토리가 열리고 IMC_Inven이 할당되어 움직이지못하고 e키로 아이템사용만 가능하고 다시 누르면 bool 조건문이 false 로 변하게되면서 IMC_Character가 할당되어 움직임이 가능하다 구현성공

구현하면서 어려웠던점 : 캐릭터 클래스에서 컨트롤러와 향상된 인풋시스템을 직접적으로 Cast하는 개념을 이해하는데 어려웠고, BindAction과 실제동작구조를 알지 못했던탓에 어떤방식으로 캐릭터가 이동을하고 점프를 하고 실제동작을 파악하는데 많이 어려웠다. 추가강의를 통해 직접 c++ 클래스에서 바인딩하고 사용해야한다는것을 배웠을때 상당히 많이 이해해서 직접적으로 구현해볼 수 있었던 것 같다.

0개의 댓글