UE4中的网络模式

Actor中的GetNetMode

Actor 中有个函数 GetNetMode 可以用来判断当前 Actor 所处的网络模式,如下

  • NM_Client: 客户端,联机模式中的客户端

  • NM_Standalone: 运行在服务器模式下,同时包含客户端的功能,也就是平常意义上的单机模式,比如在编辑器中把 number of Players 设置为1,并且不勾选Run Dedicated Server时,就会运行在这个模式下

    standalone setting

  • NM_DedicatedServer: 运行在服务器模式下,只包含服务器功能,这个是纯服务器模式,不会有客户端相关的功能运行,比如渲染相关的模块

  • NM_ListenServer: 运行在服务器模式下,同时包含客户端的功能,同时也作为主机让其他客户端连接进行联网游戏,比如很多游戏中的局域网模式。在编辑器中把 number of Players 设置为大于1,并且不勾选Run Dedicated Server时,主机就会运行在这个模式下

以上三个模式都可以认为是服务器,区别就是带不带本地玩家,能不能让其他机器连接

模式 是否带本地玩家 是否能作为主机
NM_Standalone
NM_DedicatedServer
NM_ListenServer

编译时确定的网络模式

虚幻中有一堆宏来控制编译,和网络模式相关有如下几个

  • UE_SERVER: 开了这个宏的肯定是服务器了,编译时就会把客户端相关的模块给剔除掉,比如渲染相关的
  • WITH_SERVER_CODE: 这个宏来控制网络逻辑代码的开关,如果是 !WITH_SERVER_CODE,那就是纯客户端了,在 PlatformProperties.h 中,FWindowsPlatformProperties/FMacPlatformProperties/FLinuxPlatformProperties,这三个模板类的 IS_CLIENT_ONLY 参数传的就是 !WITH_SERVER_CODE

FPlatformProperties 中封装了几个函数来判断编译是以什么模式来编译的

  • IsServerOnly: 如果是true则表示编译的时候是以DedicatedServer的模式来编译代码,会剔除客户端相关的模块代码,比如渲染模块,也不包含Editor相关的代码

  • IsGameOnly: 如果是true则表示编译时剔除了Editor相关的代码

  • IsClientOnly: 如果是true则表示编译时剔除了服务器和Editor相关的代码,这里需要注意的是,在以xxx Client模式来出包时,如果出的是Windows/Mac/Linux,则这个函数返回的是true,如果出的是移动端的包,则返回的是false,因为FIOSPlatformProperties/FAndroidPlatformProperties,没有覆盖父类中的默认IsClientOnly实现,父类的默认实现返回的的false,不明白这里为啥行为不一致

IsRunningDedicatedServer/IsRunningGame/IsRunningClientOnly

这几个函数和上面的三个函数功能类似,在非Editor模式下的返回值和上面三个函数一致,区别在于当运行Editor时,可以通过命令行来切换运行模式,具体如下

  • 命令行中包含 SERVER 或者 RUN=SERVER 时,以DedicatedServer模式模拟运行
  • 命令行中包含 GAME 时,以无Editor模式模拟运行
  • 命令行中包含 GAMEClientOnly 时,以纯客户端模式模拟运行

编译配置和GetNetMode的关系

编译配置 联机模式(主机)GetNetMode返回值 联机模式(客户端)GetNetMode返回值 单机模式GetNetMode返回值
xxx Client 无此模式 NM_Client NM_Standalone
xxx Server NM_DedicatedServer 无此模式 无此模式
Debug/DebugGame/Development/Shipping NM_ListenServer NM_Client NM_Standalone

总结

  • Actor 中有些游戏逻辑函数是服务器客户端都能调用的,如果要判断是谁触发的调用,最好的方式是通过属性Role来判断,一般 Role == ROLE_Authority 的时候就可以认为是服务器,不过要注意的是,如果客户端自己 Spawn 了一个 Actor,那么这个 ActorRole 也是 ROLE_Authority。如果只是要判断当前运行的网络模式环境,可以通过 GetNetMode 来判断。

  • 在其他地方判断运行环境,最好的方式是使用 IsRunningDedicatedServer/IsRunningClientOnly,这样保证PIE测试时也没问题