UE中如何优雅地在GUI界面禁用游戏输入

最近软工的大程需要在UE中制作GUI,我之前并没有使用过,所以基本上都是现查现用,但在搜索过程中发现网上并没有GUI打开期间禁用游戏输入的比较优雅的方案(也可能是我没找到),最后在实践中发现一种比较好的解决方案。

首先明确一下我想实现的最终效果,即游戏最终有多个GUI菜单,按下不同按钮打开不同的菜单,但是按下任意控制菜单的按键都能够关闭当前菜单,打开菜单后,用户将不能继续控制人物移动等,但游戏仍继续运行(即不停止游戏时间)。

在这里我首先是在Edit-Project Settings-Engine-Input-Bindings-Action Mappings里添加对应的按钮映射。

一种非常直接的想法是按下按钮打开GUI,之后Set Input Mode UI Only,但是UI Only模式下按钮映射将不起作用。

另一种方案是UE里UMG支持Stop Action,直接在Designer里选中该蓝图勾选Stop Action就能实现禁用游戏输入。我的最终方案也基于这个。通过勾选Stop Action,我们能实现在打开UI后禁用游戏输入,但是这个时候UI还不能用按钮关闭,我们需要在该UI的Construct Event里添加对Input Action的监听,在Input Action事件发生的回调函数里Remove From Parent,这样子就实现了关闭GUI。

但这个方案依然有一定的局限性,很容易发现,它的扩展性并不好。我们想要实现按下任意控制菜单的按钮都能关闭当前菜单,但是现在如果我们需要添加一个菜单,那么就需要在所有已有的菜单里添加对该按钮对应Input Action的监听以实现其他按钮也能关闭该菜单。

为了便于扩展,我们把这个过程抽取出来,作为BaseMenuWidget_BP,这个GUI只有一个空的Canvas,勾选Stop Action,我们在它的Construct事件中添加对所有GUI的Input Action的监听,并在回调函数中摧毁它的子UI和它本身。

每当我们想要创建一个GUI时,我们创建一个Input Action的监听,在回调函数里创建BaseMenuWidget_BP,然后将我们想要创建的GUI作为它的Child。由于BaseMenuWidget_BP已经勾选了Stop Action,所以我们想要创建的真正的GUI就不需要再勾选Stop Action。在打开后,我们按下任意控制GUI的按钮,BaseMenuWidget_BP会连带它的child一起被摧毁,就达到了我们想要的效果。

下面是BaseMenuWidget_BP的完整蓝图。之后每当我们需要新增一个菜单只需要在这里添加一个Input Action的监听。

image-20230529141722728

下面是创建一个菜单的示例,每当我们想要创建一个菜单,需要先创建BaseMenuWidget_BP,然后把真正的菜单作为它的child。这里我对添加为子窗体做了一定的封装。

image-20230529141830958

封装的内容实际上就是这样一个简单的函数蓝图。

image-20230529141842337

但是这样还有最后一个问题,我们会发现打开Widget后,需要先点一下才能focus在Widget,关闭Widget后也需要再点一下才能重新控制视角。解决方案是在BaseMenuWidget_BP的Event Construct中Set Input Mode Game And UI,主要要取消Hide Cursor During Capture,在HideWidget中将mode切回到GameMode,也就是Set Input Mode Game Only。最终的蓝图如下。

image-20230529150639735

UE中如何优雅地在GUI界面禁用游戏输入
https://jhex-git.github.io/posts/3822428522/
作者
JointHex
发布于
2023年5月29日
许可协议