本次我们梳理Lyra的角色生成。我们从引擎的加载流程开始。
引擎主循环类LaunchEngineLoop.cpp初始化
创建编辑器运行的引擎实例
调用引擎实例的初始化方法
调用引擎实例的开始方法开始游戏
UGameEngine是继承自UEgine的在其中重写了Init函数,在该函数中创建GameInstance实例
再次重写父类的Start函数,在其中启动游戏实例
在StartInstance中调用UEngine的Browse方法处理传入的URL并尝试加载地图
在地图加载函数UEngine::LoadMap中设置GameMode
GameMode创建后会自动调用生命周期函数PreInitializeComponents在这个函数里创建了游戏状态类ALyraGameState
在构造函数中创建了能力系统组件和资源管理器组件
以上就是引擎启动流程进行的一系列初始化。
接下来就是用户登录流程,从入口组件ULyraFrontendStateComponent开始。在第一篇博客中我们提到了lyra在初始场景的蓝图B_ExperienceList3D中加载了所有资产,其中就有B_LyraFrontEnd_Experience,在这个资产配置中对ULyraFrontendStateComponent组件进行了绑定:
在资源加载时隐式的把该组件添加到了LyraGameState中,已完成了组件的初始化。我们回到组件内部逻辑:
在beginPlay函数中注册了一个监听,监听资源加载完成的事件。在OnExperienceLoaded函数中,创建了一个控制流,用于处理一些列阶段性的逻辑:
FlowStep_WaitForUserInitialization(检查是否发生硬断开连接)
->FlowStep_TryShowPressStartScreen(是否显示PressStart界面)
->FlowStep_TryJoinRequestedSession(尝试加入用户请求的游戏会话)
->FlowStep_TryShowMainScreen(尝试显示主界面)
这里我们只着重看FlowStep_TryShowPressStartScreen函数,
此处调用了UCommonUserSubsystem的TryToInitializeForLocalPlay函数,进入到
UCommonUserSubsystem内部逻辑,内部代码片段太多,所以只写出简单的调用栈:
TryToInitializeForLocalPlay->TryToInitializeUser->LoginLocalUser(创建了登录完成回调作为参数传入)->ProcessLoginRequest,在ProcessLoginRequest中处理登录请求,因为在PIE以Standalone模式运行实际未触发登录请求,直接执行了之前传入的回调函数UCommonUserSubsystem::HandleLoginForUserInitialize创建本地玩家:
在gameInstance的CreateLocalPlayer中创建了LocalPlayer同时创建了PlayerController
在LocalPlayer中调用world的SpawnPlayActor函数
在World的SpawnPlayActor中对控制器进行了一些设置,最后调用gameMode的PostLogin函数处理登录后的逻辑
在PostLogin中创建玩家Pawn并开始游戏
我们继续跟代码,看它是如何创建Pawn的
此处函数以_Implementation后缀结尾,因为它使用了函数说明符BlueprintNativeEvent,支持C++默认实现和蓝图覆盖,一下是它的声明
从RestartPlayer调用到RestartPlayerAtPlayerStart在其中完成了Pawn的创建
至此,从引擎主循环启动到创建玩家的流程就结束了。