UE5插件CommonUI使用及原理剖析(Input)

CommonUI是UE5新推出的一款UI插件,原本是堡垒之夜里使用的插件,Epic就将其作为插件引入到了UE5中。他主要的功能在于两点:一是对于复杂的UI使用LayerStack的思想,对于不同层级的UI进行相应的管理,并使用栈的方式解决UI层级的响应问题;二是使用InputRouting实现对不同输入的统一适配,对于开发多平台游戏来说比较方便,通过配置配置表即可实现多平台的UI和输入适配。本篇主要着重在Input部分进行使用的详解和源码的简要剖析。

CommonUI Input的使用

CommonUI的使用参考虚幻引擎Common UI快速指南 | 虚幻引擎5.0文档,主要分为四个步骤: 1. 设置Viewport为CommonUIClientViewport。在Project Settings -> General Settings -> GameViewportClientClass 修改为CommonGameViewportClient 2. 创建InputActionDataTable进行控制器操作映射的配置。

  1. 设置 Default Navigation Actions,支持全局的点击和返回按钮功能。创建一个CommonUIInputData的蓝图类,设置Click Action和Back Action的InputAction映射,其中BackActionHandler可以在CommonUI的Widget中Override(设置一个布尔值IsBackHandler)

  2. 创建 Controller Data Assets 并且将其分配到特定平台上的特定控制器类型,可以为每个Button添加特定的Brush,通过这个设置就可以用CommonActionWidget来显示对应的Action的Icon了。 通过以上四个步骤可以实现CommonUI Input的基本设置。要让一些功能生效,最好还是要使用CommonUI提供的Widget,比如CommonActivatableWidget、CommonButtonBase等等。详细可以参考InsideUnreal的教程,或者阅读CommonUI的源码进行理解。 ### CommonUI Input源码流程梳理 通过阅读源码发现,其实CommonUI提供的不是一个完整的解决方案,我个人觉得更多的是一种思路。对于InputActionDataTable的使用,主要是在UCommonUserWidget中的RegisterUIActionBinding()函数中。在这个函数中进行InputAction的注册绑定,通过查找发现主要是三种操作: CommonActivatableWidget的Back操作,CommonButtonBase的Trigger操作,以及CommonTabListWidgetBase的Tab操作。在这些Widget中可以自定义是否Handle对应的操作。所以单单一个CommonUI对于Input的处理还是比较局限的。

调用的流程是从UCommonGameViewportClient开始。在这个类中UCommonGameViewportClient::InputKey这个函数首先处理KeyInput,然后在UCommonGameViewportClient::HandleRerouteInput中在ActionRouter里处理Input

在ActionRouter中,会将Input传递给CommonUI Widget中当前的ActiveRootNode进行处理。CommonUI会将所有的ActivatableWidget按照层级进行建树。每个节点会被抽象成为FActivatableRootNode。然后从根节点开始遍历,对于每个Child执行ProcessNormalInput,直到Input被Consume。

Activatable Widgets are abstracted as nodes in a tree using FActivatableRootNode. Nodes are arranged in a hierarchy based on the hierarchy of Activatable Widgets in the UI's widget tree. Parent nodes act as root nodes, while their children are considered child or leaf nodes.

ProcessInputNorma函数如下

这里就是通过查找绑定的ActionBindings制定绑定的相应的操作。在IDE中查找后发现,追根溯源,ActionBindings的绑定就是在上面所说UCommonUserWidget中的RegisterUIActionBinding()函数中进行的。Click (确认) 和 Back (取消)两种操作上。但是他提供了一种通用Input的处理方法,在LyraStarterGame中,就通过这种方法又自定义了一些通用的ActionBindings。 ### 参考资料 虚幻引擎Common UI快速指南 | 虚幻引擎5.0文档 InsideUnreal CommonUI Tutorial 游戏引擎应用——Unreal Engine的CommonUI插件分析 - 知乎