UE5 在启动窗口中一个项目的打开流程

简介: 前文算是捋顺了从引擎启动到打开 ProjectBrowser 的一个流程,今天就捋一下在 ProjectBrowser 面板内点击 OpenProject 后,如果开启一个项目。
ProjectBrowser 的界面逻辑索然无味,我们就从点击 Open 按钮后的打开事件开始一步一步往后推

流程格式

由于这个流程会在不同文件之间来回跳转,所以我想了一个格式,用来让跳转更清晰
流程标号. 文件名: 文件内的方法调用及主要流程
如果方法内的流程太长,我会使用 * 将主要步骤大致排列出来

开始捋

  1. SprojectBrowser.cpp 通过内部绑定到 UI 打开按钮上的 OpenProject 方法开始启动选择的项目。
  • 获取将要打开的文件的标识
  • 检查要打开的项目是不是当前已经打开的项目
  • 判断是否是一个 code 类型项目,是的话就使用 IDE 进行代码的编译,这期间出错就会直接返回
  • 检查版本是否与引擎匹配,是否升级,是否使用copy的方式打开等等常规操作
  • 最后调用 GameProjectUtils::OpenProject 方法打开指定的项目
  1. GameProjectUtils.cpp OpenProject 方法内主要就是检查项目文件各种是否合格,从命名到后缀到字符,以及文件是否存在,有一条不过就会返回,检查合格后会调用 FUnrealEdMisc::Get().SwitchProject
    我发现它是切换项目来实现打开项目的

  2. UnrealEdMisc.cpp: SwitchProject 比较有意思,它也没有直接的去打开新工程,而是通过 SetPendingProjectName 方法保存要打开的工程名称,然后向 GEngine->DeferredCommands.Add( TEXT("CLOSE_SLATE_MAINFRAME")); 添加一个 DeferredCommands

DeferredCommands 类似于一个 commandList,这里面的指令会在每帧的最后执行

  • 首先会判断是否还在构建的灯光,如果是则会直接返回
  • 判断是否需要弹警告,例如当前工程有东西没有报错,是否继续切换,是的话就继续执行,不是的话就会在后面跳过执行切换逻辑
  • DeferredCommands 添加 CLOSE_SLATE_MAINFRAME 指令
  1. EditorServer.cpp 内的 UEditorEngine::Exec_Editor 会处理上方的 CLOSE_SLATE_MAINFRAME 指令,它内部就是 获取 IMainFrameModule 然后调用他的 RequestCloseEditor

  2. MainFrameModule.h 这个 RequestCloseEditor 函数是直接写在 .h 文件里的,它的内部会调用 FMainFrameHandlerShutDownEditor

  3. MainFrameHandler.cpp 它的内部就是调用各模块的保存,停止,关闭

  • 主要处理了 GUnrealEdGEditorRootWindowGlobalTabManager
  • 最后使用 GEngine->DeferredCommands.Add(TEXT("QUIT_EDITOR")); 传递 QUIT_EDITOR 退出 Editor 的指令
  1. EditorServer.cpp 获取到 QUIT_EDITOR 命令后,调用 CloseEditor 方法

  2. UnrealEdEngine.cpp UUnrealEdEngine类继承自 UEditorEngine 上面的 CloseEditor 的声明就来自于 UEditorEngine ,所以我们可能无法直接调到 UnrealEdEngine 里的具体实现。至少我没找到直接跳到的方法,有方法的小伙伴可以给我留言哦
    这里主要是关闭了 PlayLevel 的一些东西

  • EndPlayMap();
  • EndPlayOnLocalPc();
  • RequestEngineExit(TEXT("UUnrealEdEngine::CloseEditor()"));// 尽快关闭引擎
  1. CoreGlobals.cpp RequestEngineExit 方法内设置 GIsRequestingExit = true; 为 true ,用于退出

  2. Launch.cppGuardedMain 方法内的 Tick 循环部分使用了 !IsEngineExitRequested() 来作为循环终止条件

  • IsEngineExitRequested() 内返回的就是我们上一步看到的设置的 GIsRequestingExit 的值,这里已经为 true,所以退出了 Tick 循环体
  • Editor 模式下执行到 EditorExit(); 方法
  1. UnrealEdGlobals.cpp 内的 EditorExit() 方法内主要就是保存配置,保存目录,处理剩余的线程,然后调用 FUnrealEdMisc::Get().OnExit();

  2. UnrealEdMisc.cpp 这里的 OnExit 是最终的退出函数,真难找啊。主要还是在处理一些注销,关闭,解除绑定和清理的工作。

  • 在最后的末尾阶段,用到了我们在第 3 步设置的 PendingProjName
    如果 PendingProjName 有效,则会拉起新的工程。这里会判断如果是已经绑定了 Restart,这走Restart的流程,没有的话 则重新生成编辑器实例

          bool bSuccess = false;
      if (FEditorDelegates::OnRestartRequested.IsBound())
      {
          bSuccess = FEditorDelegates::OnRestartRequested.Execute(PendingProjName);
      }
      else
      {
          bSuccess = SpawnEditorInstance(PendingProjName);
      }
    
  • 如果没有 success 则会清理 ClearPendingProjectName 直接返回

  • SpawnEditorInstance 会使用 FPlatformProcess::CreateProc 的方法重新打开带有名称的项目

到此结束 因为在最后使用 cmd 开启项目时,已经传入了项目名称,所以是会直接打开项目,就没有 ProjectBrowser
终于算是正常启动项目了,接下来可以正式看拉起项目的步骤了,就是 preinit、init、tick、exit 那些了

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容