언리얼 5.5 에 SetInputMode 에 따른 PlayerController 의 BP 와 WBP 의 사이에서의 블루프린트내 키 입력 우선 순위 관련 문의

플레이어 컨트롤러가 최초에 띄워져 있는 상태에서 BP_PlayerController 에서 개발을 위해 블루프린트 내에서 AnyKey 이벤트를 받아 필요한 처리를 하고 있습니다.

그리구 이후에 위젯을 하나 띄워서 해당 위젯에서 마찬가지로 위젯 블루프린트에서 AnyKey 이벤트를 받아 필요한 처리를 하게 구성했습니다.

자 이런 상황에서 처음에 에디터를 실행하면 플레이어 컨트롤러만 있으므로 당연히 BP_Playercontroller 에서 처리하는게 문제 없이 잘되는게 맞겠죠.

현재 SetInputMode 는 GameModeOnly 로 설정되어 있습니다. 이 상태서 이제 위젯을 하나 띄웁니다. 그러면 이제 위젯의 블루프린트내 Anykey 이벤트로 처리가 됩니다.

BP_PlayerController 의 이벤트가 가로채지는거죠 . 이제 위젯을 RemoveFromParent 로 해서 Viewport 에서 지웠습니다. 그럼 다시 BP_PlayerController 의 Anykey 이벤트 처리가 다시 됩니다.

그리고 이제부터 문제 상황입니다. 이제 똑같은 위젯을 다시 띄웁니다.

처음 들어와서 최초에 위젯을 띄울때는 위젯을 띄우면 위젯 블루프린트가 BP_PlayerController 보다 우선 순위가 높아서 anykey 이벤트가 위젯쪽에서 처리가 됩니다.

그런데 이후에 위젯을 지웟다가 다시 똑같은 위젯을 띄우는 경우엔 위젯쪽에서 처리가 안됩니다. 우선 순위가 BP_PlayerController 이 높아서 위젯쪽에서 anykey 이벤트가 발생을 안합니다.

그러면 여기서 질문이 애초에 인풋 모드가 GameOnly 상태라서 위젯을 띄웟을때 anykey 이벤트가 안가야 하는거 아닌가요?

테스트를 위해서 위젯을 띄우고 AddtoViewport 만 한 상태입니다. ​

관련 상황에서 이것이 언리얼쪽 관련 버그인지 아니면 필요한 처리가 저희쪽에서 안된건지 판단이 어렵습니다.

이와 관련해서 문의 드립니다. 감사합니다.​

안녕하세요.

UserWidget에서 Any Key 이벤트를 사용할 시 RemoveFromParent 호출 이후, 해당 UserWidget Instance를 다시 AddToViewport하여 화면에 띄울 시, AnyKey 이벤트가 작동하지 않는 부분에 대해서 말씀하시는 것 같습니다.

UserWidget에 해당 이벤트를 사용할 시, UserWidget의 Instance가 생성될 때 해당 이벤트가 등록됩니다.

즉 Create Widget을 통해 해당 UserWidget이 생성되면, 해당 이벤트는 자동으로 UserWidget에서 생성된 InputComponent에 바인딩됩니다.

그렇기에 바인딩 된 이벤트는 UserWidget의 Input Component가 제거되면 더 이상 동작하지 않게 됩니다.

일반적으로 RemoveFromParent가 호출이 될 때, InputComponent도 함께 제거되므로, 이 시점을 기준으로 이벤트도 더이상 작동하지 않습니다.

그래서 다시 AddToViewport 하면 InputComponent가 제거되었기 때문에 키 바인딩에 대한 이벤트를 받을 수 없습니다.

우회방법으로는 RemoveFromParent 호출 이후 Create Widget을 하여 다시 인스턴스를 생성하는 방법이 있을 것 같습니다.

또한, 인풋 모드가 Game Only 모드 상태인 경우에 Widget의 Any key 이벤트가 발생했던 이유는 Widget에서도 Input Component를 사용하여 이벤트가 바인딩 되기 때문에 이에 대한 입력이 오도록 되어 있습니다.

위젯에서 키 입력을 받는 방법에는 Slate Application 단계에서부터 내려오는 On Key Char, On Key Down, On Key Up과 같은 함수를 사용하면 키에 대한 인풋을 받을 수 있습니다.

감사합니다.

안녕하세요, 저희쪽 회신도 늦어진 점 죄송하다는 말씀을 먼저 드립니다.

현재 겪고 계신 현상에 대해서 ​내부 개발팀에 문의해보았고, 결론부터 말씀드리면 이는 현재 의도된 디자인이라고 합니다.

내부적인 정의로 Keyboard event와 같은 Legacy Action, 축에 대한 Axis Mapping, 그리고 가장 최근에 소개된 Enhanced Input을 GamePlay Event라고 정의하고 있습니다.

Input Mode에서 'Game’은 이러한 GamePlay Event를 ​칭하는 것으로, 결국 Player Controller의 Input Mode가 Game Only 또는 Game And UI일 때 이러한 이벤트들이 활성화되도록 디자인되어 있다고 합니다.

이는 이벤트 자체가 Player Controller에 정의되어 있는지, User Widget에 정의되어어디에 정의되어 있는지는 고려하지 않고 활성화/비활성화가 적용된다고 볼 수 있습니다.

이외에 User Widget 어떤 식으로 이벤트를 오버라이딩하는지에 대해서는 이전의 김수왕님 답변을 참고 부탁드리겠습니다.

조금은 혼란스런 답변이실 수 있을 것으로 생각되는데요, 구현하고자 하시는 동작을 말씀주시면 현재 상태에서의 방향을 안내드려볼 수 있도록 하겠습니다.

또한, 엔진 커스터마이징을 통해서라도 원하는 동작을 구현하고자 하실 경우 말씀주시면 해당 안내도 드려볼 수 있도록 하겠습니다.

부족한 답변이지만 프로젝트에 도움이 되었으면 합니다.​

안녕하세요.

오히려 구체적으로 질문을 주시어 내용을 이해하는데 큰 도움이 되었습니다​.

현 상황에 대해서 조금 납득하기 어려운 부분이 있으실 것으로 예상되지만, 현재 이러한 부분들은 의도된 개발 방향이라는 답변을 들어 이를 전달드립니다.

송구하지만 조금 더 구체적으로 주신 내용들을 통해 설명드려보면 다음과 같습니다.

​현재 작업중인 동작에 대해서 설명을 드리면 HUD 용 위젯을 화면에 띄웠을때 개발내 테스트 동작을 위해서 Hud Widget 에 BP 에서 AnyKey 바인딩같은 Key Event 액션에 대해 특정한 개발용 함수를 호출하게 하였습니다. 그런데 이게 최초로 Widget 이 화면에 띄워지는 경우에는 해당 Widget 의 BP 에서 제대로 Key Event 처리가 됩니다. 위젯을 띄울때는 InputMode 를 GameAndUI 이걸로 세팅하였습니다.

​=> 전달주신 내용에서 Key Event는 앞서 말씀드렸던 GamePlay Event에 속합니다. 따라서, Input Mode를 GameOnly, GameAndUI 둘 중 어떤 것을 설정하셔도 이벤트를 받을 수 있도록 활성화됩니다.

그리고 실제 내부 시스템 상에서는 어떠한 경우에서도 이벤트를 받는 리스너는 Player Controller지만, Player Controller 내에는 Input Stack이라는 형태로 본인 것을 제외한 외부의, 즉 여기서는 Widget BP에서의 Input Component를 들고 있게 됩니다.

Widget BP가 다수가 있을 경우 Stack의 FIFO(First In First Out) 자료구조의 특성상 가장 최근에 등록된 Widget BP가 우선권을 가져가게 됩니다.

한가지 부가적으로 말씀드릴 사항으로 Widget BP에는 Set Input Action Blocking이라는 설정 함수를 두고 있습니다.

기본적으로 해당 설정은 False로 되어있으며, False에서는 Widget BP상에서 정의한 이벤트만 처리되고 나머지들은 그 후순위의 리스너에서 처리되도록 하고 있습니다.

예를 들어, 문의주신 상황에서 Player Controller에는 Key 1, 2에 대한 이벤트를 정의하고 있고 Widget BP에서는 2에 대한 이벤트만 정의하고 있다면,

Widget BP에서는 2의 이벤트가 처리되고, Player Controller는 1의 이벤트만 처리할 수 있는 상태가 됩니다.

참고로 해당 설정값을 True로 설정하실 경우, Widget BP의 이벤트만 처리되고 후순위 이벤트들은 모두 생략하도록 동작하고 있습니다.

제가 겪고 있는 문제는 PlayerController 에서도 KeyEvent 처리를 하게 되는 경우 동작에 혼선이 오는 경우입니다.

다시 설명을 드리면 BP_PlayerController 에도 KeyEvent 처리를 하는게 있고 해당 Hud Widget 의 BP 에서도 KeyEvent 처리를 하는 동작이 있는데 위젯이 처음에 띄워질때는 Widget 의 KeyEvent 가 PlayerController 보다 먼저 처리되고 위젯을 RemoveFromParent 로 삭제한후 다시 위젯을 띄우게 되면 PlayerController 의 KeyEvent 처리가 먼저 되는 상황입니다.

=> Widget의 KeyEvent 처리가 등록되는 시점은 혼란스러워시겠지만, Add to Viewport 시점이 아닌 Create Widget 시점입니다.

조금 더 정확하게 말씀드려보면 On Initialized 시점에 이러한 이벤트 등록처리가 진행되고 있습니다.

실제로 Create Widget 이후 Add to Viewport를 실행하지 않더라도 생성된 Widget에서의 Key Event가 호출되는 것을 확인할 수 있습니다.

Remove from Parent 시점에는 Destruct가 호출되면서 등록된 이벤트들을 해제하면서 내부의 이벤트 리스너 용 모듈인 Input Component 역시 삭제 처리하고 있습니다.

이후 Add to Viewport로 다시 가시화는 가능하나, 이때는 On Initialized를 호출하지 않기에 이벤트 리스너가 활성화되지 않게 되고 있습니다.

이 상태에서는 기존의 리스너였던 Player Controller가 지속적으로 이벤트 리스너로써의 역활을 수행하게 됩니다.

만약 이벤트 리스너로써의 동작의 일관성(항상 Widget이 보여질 때, 이벤트를 처리하도록)을 유지하시기 위해서는 Create Widget > Add to Viewport의 전체 초기화 단계를 다시 진행하는 것이 필요합니다.

이것이 언리얼에서 의도한 동작인건지 아니면 문제가 되는 상황인건지 그것이 궁금합니다.

=> 납득하시기 어려운 내용들이 많을 것으로 보입니다.

다만, 해당 내용을 개발팀에 문의해본 결과 이는 의도된 내용이라는 답변을 들을 수 있었습니다.

저희쪽 EGK 내부에서도 해당 디자인을 검토 중에 있으며, 그 결과에 따라 에스컬레이션해서 관련 디자인에 대한 변경요청하는 것을 고려하고 있습니다.

이러한 과정에는 다소 시간이 소요될 수 있다는 점에 대해서도 거듭 양해의 말씀을 드립니다.

추가로 의도한 동작이라면 어떠한 조건으로 우선순위가 설정되는건지 알고 싶습니다.

​ => 지금까지 전달드린 내용들이 모두 관련되어 있어, 내용들을 한번 정리하여 전달드려보면 다음과 같습니다.

  • Key Event는 GamePlay Event의 하나로 Player Controller의 Input Mode가 Game 또는 GameAndUI일 경우 활성화 됨
  • Key Event의 정의를 Widget BP에 하더라도 실질적으론 Player Controller에서 모든 리스너들을 관리하고 있음
  • 가장 마지막에 생성된(Create Widget) Widget BP에서 이벤트에 대한 가장 높은 우선권을 ​가짐
  • Create Widget 후, Add to Viewport하지 않더라도 이벤트 리스너로써의 동작은 등록됨
  • 생성된 Widget BP의 Set Input Action Blocking 기본값은 False로, 본인이 정의하고 있는 Key Event를 처리하고 나머지는 후순위의 리스너로 넘김
  • Widget BP에서 Set Input Action Blocking를 True로 변경 호출할 경우, 최상위 리스너인 Widget에서만 이벤트를 처리함
  • ​Widget BP의 이벤트 리스너로써의 기능은 Remove from Parent가 호출될 때이며, 이후 다시 이벤트 리스너로 동작시키기 위해서는 Create Widget부터 다시 실행 필요

다시 한번 부족한 답변을 드리는 점 양해의 말씀을 드립니다.

내부적으로 관련 모듈의 디자인에 대한 검토 후 에스컬레이션이 진행될 경우 해당 내용의 진행 상황을 공유드려 볼 수 있도록 하겠습니다.​

또한 전달드린 내용에서 모호한 점이나 추가 문의가 있으실 경우 말씀주시면 그에 대한 리서치를 진행할 수 있도록 하겠습니다.​

감사합니다.​

안녕하세요, 전동수님!

드린 답변이 도움을 드렸다니 저야말로 기쁘며, 좋은 말씀 너무 감사하다는 말씀을 드립니다.

지난 문의에서 이메일로 소통 중이라고 하시어 EPS 티켓은 Closed 상태로 변환하도록 하겠습니다.

혹시 문제가 있다 판단되시면 말씀주시면 다시 Pending 상태로 전환하겠습니다.

다음 티켓으로 찾아뵐 때까지 건강하시고 프로젝트의 성공도 바라겠습니다.

감사합니다.

안녕하세요. 늦게 회신을 드리게 되어서 죄송합니다.

올려주신 내용에 감사합니다. 하지만 말씀하신 내용들이 저에게 많은 도움이 되었습니다만, 제가 원하던 현상에 대한 만족스러운 답은 아닙니다.

제가 질문으로 올린 내용은 서브레벨로 되어있는 레벨에서 시작시 PlayerController 과 UMG 위젯이 화면에 그려지는 상황에서 PlayerController 과 UMG 위젯의 블루프린트내에서 테스트를 위해

Any Key 이벤트를 주었고 (*에디터 환경입니다. 따로 디벨롭 빌드나 쉬핑 빌드로 한건 아닙니다.) ​

처음에는 PlayerController 이 Any 키 이벤트에 대해 우선순위가 있었지만 이제 위젯을 삭제하고

다시 같은 위젯을 재 생성해서( Collpase 가 아니라 말그대로 CreateWidget 으로 새로 생성) 화면에 그려주고 나면

UMG 위젯이 Any 키 이벤트에 대해 우선순위를 가지는 현상에 대한 질문이였습니다.

이 상황이 언리얼 5.5.4 에서의 버그인건지 아니면 제가 UMG 위젯 사용을 잘못해서 그러는건지 그에 따른 판단을 구하고 싶어 질문을 올렸습니다.

안녕하세요.
사이트에서 적어주신 답변에 문의를 추가해볼려고 했지만 사이트에 접속이 안되어서 이메일로 회신을 보내봅니다.

제가 언리얼에 익숙하지 않아서 두서없이 질문을 올려서 혼란이 오셨을수도 있을거 같아 미리 사과를 드려봅니다.

현재 작업중인 동작에 대해서 설명을 드리면 HUD 용 위젯을 화면에 띄웠을때 개발내 테스트 동작을 위해서 Hud Widget 에 BP 에서 AnyKey 바인딩같은 Key Event 액션에 대해 특정한 개발용 함수를 호출하게 하였습니다. 그런데 이게 최초로 Widget 이 화면에 띄워지는 경우에는 해당 Widget 의 BP 에서 제대로 Key Event 처리가 됩니다. 위젯을 띄울때는 InputMode 를 GameAndUI 이걸로 세팅하였습니다.

제가 겪고 있는 문제는 PlayerController 에서도 KeyEvent 처리를 하게 되는 경우 동작에 혼선이 오는 경우입니다.
다시 설명을 드리면 BP_PlayerController 에도 KeyEvent 처리를 하는게 있고 해당 Hud Widget 의 BP 에서도 KeyEvent 처리를 하는 동작이 있는데 위젯이 처음에 띄워질때는 Widget 의 KeyEvent 가 PlayerController 보다 먼저 처리되고 위젯을 RemoveFromParent 로 삭제한후 다시 위젯을 띄우게 되면 PlayerController 의 KeyEvent 처리가 먼저 되는 상황입니다.

이것이 언리얼에서 의도한 동작인건지 아니면 문제가 되는 상황인건지 그것이 궁금합니다.
추가로 의도한 동작이라면 어떠한 조건으로 우선순위가 설정되는건지 알고 싶습니다.

감사합니다.

안녕하세요. Lee Jay 님.

귀한 시간을 내어 답변을 작성해주셔서 정말 감사합니다.

제 질문의 핵심을 정확히 파악하고 남겨주신 상세한 답변에 정말 경탄했습니다.

말씀해주신 내용을 토대로 코드를 수정하니 이슈가 해결된 것은 물론, 제가 놓치고 있던 근본적인 원리에 대해 더 깊게 이해하게 되었습니다.
제가 문의했던 모든 내용에 대한 상황이 다 이해가 되었습니다.

정말 너무 너무 너무 상세하고 자세한 답변에 다시 한번 깊은 감사를 드립니다.

항상 건강하시고 행복하세요. 정말 너무 감사했습니다.​