UE5.8 Common UI 喂饭级专题

UE5.8 Common UI 专题(八):Modal、异步加载与弹窗

围绕 bIsModal、Modal Stack、Confirm Dialog、CommonLoadGuard、CommonLazyImage、CommonLazyWidget、Queue 和异步回调清理,讲真实项目弹窗和加载界面怎么做。

总览

游戏 UI 里最容易乱的是弹窗:确认框、奖励、网络错误、购买提示、加载遮罩、好友邀请都想盖在最上面。Common UI 给你的工具是:Modal 页面、Modal Stack、Queue、LoadGuard 和 Lazy Widget/Image。

UE5.8 Common UI 专题(八):Modal、异步加载与弹窗 配图
Modal 负责阻断输入,LoadGuard 负责异步期间的可视反馈,Queue 负责弹窗顺序。

Modal 页面怎么定义

UCommonActivatableWidgetbIsModal。Modal 的语义是:它在前台时,下面的页面不应该继续接收输入。确认框、购买弹窗、删除存档都应该是 Modal。

确认框建议:

  • 继承 CommonActivatableWidget
  • bIsBackHandler=true
  • bIsModal=true
  • Desired Focus 返回“取消”按钮,而不是危险的“确认”按钮
  • Confirm 和 Cancel 都 Deactivate 自己,并把结果回调给打开者

Modal Stack 不要和 Menu Stack 混用

把确认框 Push 到 Layer_Modal,不要 Push 到 Layer_Menu。这样设置页仍然在下面,但输入被 Modal 抢走;确认框关闭后,设置页的焦点和输入配置能恢复。

UConfirmDialog* Dialog = LayerModal->AddWidget<UConfirmDialog>(
    ConfirmDialogClass,
    [Message, OnResult](UConfirmDialog& Widget)
    {
        Widget.Setup(Message, OnResult);
    });

CommonLoadGuard

UCommonLoadGuard 像一个会显示加载状态的 Border。它可以 SetIsLoading(true),也可以 GuardAndLoadAsset,等软引用资源加载完成后再显示内容。

适合:

  • 商店物品大图异步加载。
  • 角色预览 Widget 异步创建。
  • 网络请求未返回时锁住局部面板。
  • 大地图缩略图未加载时显示 spinner。
LoadGuard->SetLoadingText(NSLOCTEXT("UI", "Loading", "加载中"));
LoadGuard->SetIsLoading(true);

RequestInventoryAsync([this](const FInventoryData& Data)
{
    RefreshInventory(Data);
    LoadGuard->SetIsLoading(false);
});

页面 Deactivate 时要取消请求或忽略回调,避免异步返回后刷新已关闭页面。

CommonLazyImage 和 CommonLazyWidget

LazyImage 适合软引用图片,LazyWidget 适合软引用 Widget Class。项目中商店、图鉴、任务详情经常要用它们。不要在打开页面的一瞬间同步加载大量图标,否则菜单卡顿会很明显。

Queue 处理非阻塞提示

奖励 Toast、成就提示、保存成功提示适合 CommonActivatableWidgetQueue。当前 Toast 播放动画后 Deactivate,Queue 自动显示下一个。不要把这些提示做成 Modal,玩家会烦。

使用案例:删除存档

流程:

  1. 玩家长按删除按钮。
  2. 打开 Modal 确认框。
  3. 默认焦点在“取消”。
  4. Confirm 后确认框进入 Loading 状态,禁用按钮。
  5. 异步删除完成,确认框 Deactivate。
  6. Toast Queue 显示“存档已删除”。

这个流程里每一步都在自己的层:列表页在 Menu,确认框在 Modal,成功提示在 Toast。

常见坑

  • 确认框放 Menu Stack,Back 后返回路径错乱。
  • Modal 没设置 Desired Focus,手柄打开后无法选择按钮。
  • 异步回调里直接访问已 Deactivate 的页面。
  • Loading 遮罩只是视觉层,没有阻止底下按钮点击。
  • Toast 用 Modal,导致每个奖励提示都挡玩家输入。

源码依据

UCommonLoadGuard 注释说明它类似 Border,但能在内容加载或准备期间隐藏主内容、显示 spinner 和可选文本,并支持 GuardAndLoadAssetUCommonActivatableWidget 提供 bIsModal、Desired Input Config、Back Handler 和 Activation 生命周期。UCommonActivatableWidgetQueue 适合一次显示一个 widget,当前停用后再显示下一个。

源码路径索引

  • CommonUI/Public/CommonActivatableWidget.h
  • CommonUI/Public/CommonLoadGuard.h
  • CommonUI/Public/CommonLazyImage.h
  • CommonUI/Public/CommonLazyWidget.h
  • CommonUI/Public/Widgets/CommonActivatableWidgetContainer.h