UE4项目_EveryThing开发有感之菜单UI管理
老规矩,-_-,随意写了,语文不好,懂意思就行.
项目地址:https://github.com/GuAoDiao/EveryThing
本文的内容主要为菜单里面的UI管理
具体就是菜单相关多UI之间来回互相切换,非常容易混乱.
这里提供一个自己的管理方案,主要采用的是状态机,状态切换.
定义一个enum,罗列所有可能性,
UENUM(BlueprintType) enum class EMenuUIState : uint8 { StartUp, MainMenu, CreateArchive, ArchiveList, MasterInterface, Storehouse, HouseMenu, HouseCreate, HouseList, Config, LoadingScreen, ErrorDialog, Unknown };
核心函数,用来管理UI之间的状态
// 函数名称变量名称很明白了,就不做解释了 public: EMenuUIState GetCurrentGameUIState() const { return CurrentGameUIState; } bool IsTargetGameUIState(EMenuUIState InGameUIState) const { return InGameUIState == CurrentGameUIState; } void ToggleToNewGameUIState(EMenuUIState InGameUIState); void ToggleToLastGameUIState(); private: void FinishOldGameUIState(EMenuUIState InGameUIState); void StartNewGameUIState(EMenuUIState InGameUIState); private: EMenuUIState CurrentGameUIState; EMenuUIState LastGameUIState;
核心步骤
/// 切换状态时 void AEveryThingHUD_Menu::ToggleToNewGameUIState(EMenuUIState InGameUIState) { // 如果新的状态即要展示的UI不是加载界面或错误提示,则移除当前展示的UI // 错误提示弹出,加载界面弹出时,背景UI都不会发生改变,所以不移出 if (InGameUIState != EMenuUIState::LoadingScreen && InGameUIState != EMenuUIState::ErrorDialog) { FinishOldGameUIState(CurrentGameUIState); } // 更新UI状态 LastGameUIState = CurrentGameUIState; CurrentGameUIState = InGameUIState; // 展示新的UI StartNewGameUIState(CurrentGameUIState); } /// 移除和展示,根据不同的状态写相应的处理 { // 移除 case EMenuUIState::MainMenu: ShowMainMenu(); break; // 展示 case EMenuUIState::MainMenu: if (MainMenu) { MainMenu->RemoveFromParent(); } break; }
目前为止,我们就可以通过切换状态来切换显示的UI了.
因为是状态机管理,所以直接切换到新状态就可以了,如果UI复杂,有特殊需求,也可以修改扩展.特殊实现,如错误提示
// 如题,特殊状态错误提示时,需要一个错误信息,可以在切换UI后手动设置. void AEveryThingHUD_Menu::SetErrorDialogMessage(const FString& ErrorMessage) { if (IsTargetGameUIState(EMenuUIState::ErrorDialog) && ErrorDialog) { ErrorDialog->SetErrorMessage(FText::FromString(ErrorMessage)); } }
下面是使用:
void UArchiveRow::LoadArchive()
{
UEveryThingGameInstance* OwnerETGI = GetOwningPlayer() ? Cast<UEveryThingGameInstance>(GetOwningPlayer()->GetGameInstance()) : nullptr;
AEveryThingHUD_Menu* OwnerMenuHUD = GetOwningPlayer() ? Cast<AEveryThingHUD_Menu>(GetOwningPlayer()->GetHUD()) : nullptr;
if (OwnerETGI && OwnerMenuHUD)
{
// 加载存档成功,跳转至主界面
if (OwnerETGI->LoadArchiveFromName(ArchiveName))
{
OwnerMenuHUD->ToggleToNewGameUIState(EMenuUIState::MasterInterface);
}
else
{
// 展示错误信息
OwnerMenuHUD->ToggleToNewGameUIState(EMenuUIState::ErrorDialog);
OwnerMenuHUD->SetErrorDialogMessage(TEXT("Can't load Archive"));
}
}
}
注:抛砖引玉,欢迎讨论,实现更好效果。