开发过程中总会遇到一些较小众或相对定制化的需求,有的时候问题看起来并不复杂,但做起来总差点意思,又检索不到资料,最终仍是浪费不少时间......

一般来讲,我们设置GameMode都是在WorldSettings里面的,或者配置ProjectSettings里面的DefaultGameModes来全局设置。

WorldSettings内的GameModeOverride
ProjectSettings内的DefaultGameMode

然而,上述的方法都只能在编辑器内提前配置好将要使用的GameMode,无法在游戏时动态决定GameMode。所以,有没有一种方法可以在运行游戏时决定Map使用哪一个GameMode呢?

省流版

  1. 调用UGameplayStatics::OpenLevel()函数
  2. 传入Options参数"Game=XXX",或者直接在LevelName里面拼接好"LevelName?Game=XXX",其中XXX是GameMode别名
  3. 在ProjectSettings中设置GameModeClassAliases配置GameMode别名

分析版

答案是可以,虽然无法在游戏任意时刻切换当前的GameMode,但是可以在打开关卡时决定选用的GameMode,玄机就在UGameplayStatics::OpenLevel的参数里。

一般来讲,我们掉这个函数的时候会忽略掉Options参数,而其实OpenLevel里会将LevelName参数和Options参数拼接形成一个Url,格式大致为"LevelName?Options"。

打开关卡时,在GameInstance里会根据刚才传输的Url设置当前Map的GameMode,此时会解析字符串"Game=",而该参数即作为GameMode的参数。

而GameMode参数应该传入什么呢?其实解析到的GameMode字符串会作为UGameMapsSettings::GetGameModeForName()的参数被调用,在该函数内会检查它是否为GameMode的别名。简单来说,Game=XXX需要填写的是GameMode的别名

那GameMode的别名又是什么?这个别名的说法来自于GameMapSettings的一个成员,也就是说直接在ProjectSettings中找这个配置项直接配置即可。

至此,通过传入的参数,GameInstance内可以拿到需要覆盖的GameMode类,然后成功完成打开关卡时切换指定的GameMode。