找回密码
 立即注册
查看: 563|回复: 9

使用UE4开发的游戏,服务器怎么开发?

[复制链接]
发表于 2021-12-3 22:01 | 显示全部楼层 |阅读模式
正如其他答案提到的,DS出发点是解决FPS同步,对同步精度和延迟的追求是很高的。核心特性包括:客户端预测,服务器校验,客户端状态回退,延迟补偿,replay等等。乍看之下MMO不用这么高端的特性,再加上原生DS承载量低,有的小可爱看着DS这一大坨代码,很容易产生自己撸一个更简单的勇气。
下面简要讲下,如果放弃DS你损失的是什么:

  • 优化的网络传输。UE4在UDP上做了一层网络协议,专门用于DS通信。这是根据游戏特点专门优化的,能根据频率/重要度/数据格式等条件选择最优的传输方式(可靠/非可靠),以及数据压缩,拆合包等。网络传输的技术迭代很慢的,这块可说是epic数十年沉淀,一般人很难比他写的更好。
2. Actor的属性同步和RPC。也就是编辑器里跟同步有关的功能都只能看不能用。实际上手撸服务器最大的隐含代价就是:你服务器的游戏对象跟客户端的Actor一定是异构的,意味着你必须放弃基于Actor的整个gameplay framework,以及相关的大量功能,导致蓝图基本不可用,导致你要实现自己的脚本方案,导致……此处太多不展开了。
3. ReplicationGraph,也就是AOI,这个简单,小可爱撸一撸问题不大。
4. 动画和物理同步。主要是RootMotion和碰撞同步(武器命中),以及环境动画,破碎这些策划喜欢的东西。
5. AI行为树。嗯,UE4的行为树依赖character,character同步又依赖DS。抛弃DS意味着,你将损失一颗能断点单步可视化调试的行为树。
如果你MMO标准很低,上述内容都不需要……那么有一说一,你这个MMO很难活下去啊。
所以DS设计上的特点(游戏对象同构,和引擎全层次耦合)导致了,完全抛弃DS相当于把引擎阉割成渲染器。如果你不能接受DS的高消耗/低承载缺点,理智的做法还是去了解它,改进它,根据真实的数据和需求一步步迭代,银弹是不存在的。这里提供几个思路:

  • 首先是工程层面,减少不必要的component同步,用好骨骼LOD,ReplicationGraph配置足够的fallback层级和粒度等基操。
  • 简化原生的FPS同步方案,降低CPU消耗。比如DS不计算位置校验(对应的客户端也不需要状态回退了),更激进的比如DS跳过大部分物理模拟,关闭动画更新等。
  • DS对线程的使用是谨慎的(相对于客户端),因此物理机多开DS进程可能带来提升,实例之间也可以实现某种程度的负载均衡。
  • 考虑到每个DS进程都会独立加载游戏资源,造成内存浪费,可以实现某种单进程多位面,降低内存占用和包广播量。
  • 动态负载均衡,动态AOI之类的高端玩法,可参见SpatialOS的UE4插件。
最后,关于客户端服务器分工也说两句。以前很多客户端和服务器都搞异构游戏对象,导致两边游戏对象的生存环境完全不同,分工是为了降低心智负担,其实挺扭曲的。DS设计上是同构的,你调的RPC你自己实现啊,这时候执着于分工是一种退步。
发表于 2021-12-3 22:01 | 显示全部楼层
正如其他答案提到的,DS出发点是解决FPS同步,对同步精度和延迟的追求是很高的。核心特性包括:客户端预测,服务器校验,客户端状态回退,延迟补偿,replay等等。乍看之下MMO不用这么高端的特性,再加上原生DS承载量低,有的小可爱看着DS这一大坨代码,很容易产生自己撸一个更简单的勇气。
下面简要讲下,如果放弃DS你损失的是什么:

  • 优化的网络传输。UE4在UDP上做了一层网络协议,专门用于DS通信。这是根据游戏特点专门优化的,能根据频率/重要度/数据格式等条件选择最优的传输方式(可靠/非可靠),以及数据压缩,拆合包等。网络传输的技术迭代很慢的,这块可说是epic数十年沉淀,一般人很难比他写的更好。
2. Actor的属性同步和RPC。也就是编辑器里跟同步有关的功能都只能看不能用。实际上手撸服务器最大的隐含代价就是:你服务器的游戏对象跟客户端的Actor一定是异构的,意味着你必须放弃基于Actor的整个gameplay framework,以及相关的大量功能,导致蓝图基本不可用,导致你要实现自己的脚本方案,导致……此处太多不展开了。
3. ReplicationGraph,也就是AOI,这个简单,小可爱撸一撸问题不大。
4. 动画和物理同步。主要是RootMotion和碰撞同步(武器命中),以及环境动画,破碎这些策划喜欢的东西。
5. AI行为树。嗯,UE4的行为树依赖character,character同步又依赖DS。抛弃DS意味着,你将损失一颗能断点单步可视化调试的行为树。
如果你MMO标准很低,上述内容都不需要……那么有一说一,你这个MMO很难活下去啊。
所以DS设计上的特点(游戏对象同构,和引擎全层次耦合)导致了,完全抛弃DS相当于把引擎阉割成渲染器。如果你不能接受DS的高消耗/低承载缺点,理智的做法还是去了解它,改进它,根据真实的数据和需求一步步迭代,银弹是不存在的。这里提供几个思路:

  • 首先是工程层面,减少不必要的component同步,用好骨骼LOD,ReplicationGraph配置足够的fallback层级和粒度等基操。
  • 简化原生的FPS同步方案,降低CPU消耗。比如DS不计算位置校验(对应的客户端也不需要状态回退了),更激进的比如DS跳过大部分物理模拟,关闭动画更新等。
  • DS对线程的使用是谨慎的(相对于客户端),因此物理机多开DS进程可能带来提升,实例之间也可以实现某种程度的负载均衡。
  • 考虑到每个DS进程都会独立加载游戏资源,造成内存浪费,可以实现某种单进程多位面,降低内存占用和包广播量。
  • 动态负载均衡,动态AOI之类的高端玩法,可参见SpatialOS的UE4插件。
最后,关于客户端服务器分工也说两句。以前很多客户端和服务器都搞异构游戏对象,导致两边游戏对象的生存环境完全不同,分工是为了降低心智负担,其实挺扭曲的。DS设计上是同构的,你调的RPC你自己实现啊,这时候执着于分工是一种退步。
发表于 2021-12-3 22:04 | 显示全部楼层
虚幻自带的服务器感觉上确实是做房间型的更合适,特别是那种Host-Join的(RTS),或者大厅-房间型的,本身的流程都已经建立起来了,按照示例、搭BP就可以完成绝大多数的工作,甚至包括Steam接入。复杂一点的情况,社区里之前看到过讨论改自动匹配,感觉也不算很麻烦。

关于前后后台分工的问题

我参与的第一个项目(C++)就是一套游戏对象结构,通过SERVER宏和CLIENT宏来确定是服务器还是客户端跑,所以后来在UE里面遇到这套体系的时候感觉还是挺亲和的。
后面也参与过那种服务器逻辑和对象体系跟客户端完全分离,互相完全没有关系这种情况。这个团队的开发模式是客户端逻辑组和服务器逻辑组也完全分离,实际工作时,存在客户端程序和服务器程序互相之间等待、推诿、甩锅的情况。
而且后面我加功能的时候,感觉上,服务器的核心对象体系和客户端的核心对象体系(就是排除纯表现逻辑外的数值逻辑),事实上对价。但是却需要在维护时,在各端按照不同的对象体系和标准来维护。
无非是客户端是个CActor-CComponent,服务器名字改成SActor-SComponent,方法少一些多一些的区别。虽然,也不会增加太多编程心力,但是同时打开两个VS,看着左边写右边,看着右边写左边,也不觉得会很舒服就是了。
就我个人而言,没有进一步再想,但是目前没有感觉到服务器-客户端逻辑代码分离的优势。
统一结构下工作久了,强制自己养成了思考问题时强制思考一个对象的数值逻辑和表现逻辑的习惯,习惯之后感觉还是挺舒服的。特别是没有那种需要等待或者扯皮这样的烦心事了。

关于MMO

很早虚幻官方就提到过,大意我印象里是,有条件能做MMO的公司,基本上各自有各自的要求和解决方案,虚幻自己专门提供一套感觉有点鸡肋,因为这些公司各自项目的要求差别较大、肯定不会去用你提供的。同时,鼓励社区提供解决方案。
很早之前的印象,可能不准,有兴趣可以去论坛查找。
之前看到过KBEngine、Photon都有对应的解决方案和Samples,社区里之前也有一些其它的解决方案。
就代码的情况来看,通过一些Network底层的扩展,可以做到服务器逻辑跑DS,但架构更复杂。比如玩家登陆、先经过Login服务器和World服务器,再分配到具体的逻辑服务器(DS)上去,但做起来想来坑也不会少。
当然也可以选择完全抛弃DS,自己重新按照自己的方式来整合服务器客户端代码。
比如打包成dll,整合进自己的服务器架构里面,通信不用RPC,自己写一套新的(当然也可以选择替代默认RPC)
甚至,可以客户端服务器逻辑的完全分离,服务器完全新写一套,通信当然也是走自己的。

大房间:ARK和Atlas

虚幻项目里这两个项目是那种,玩家可以自己架设服务器,服务器支持人数一般在70~200这样的。不追求万人同服,追求私服遍地开花这种样子的游戏,有点MC那种感觉。
这两个游戏的服务器是可以从Steam上作为工具下载下来的.
ARK是非常明显的标准DS程序。
Atlas则是在DS外,自己写World服务器和数据服务器,启动时根据World配置,创建多个Ds实例,通过World服务器进行统一管理(跨地图迁移等)。这从结构上来说已经很接近于传统MMO服务器的核心结构了
这两个游戏单一ds承载上限不算高,这点可能跟服务器算的东西有点多有关。虽然个人没有尝试,但是感觉上,自己的游戏设计上如果能够降低一些负载,理论上应该承载上限还能高一些。
比如一般情况下,Server加载的地图和Client一致,但是其实可以不一致,通过设置一些标记或者改一些代码,有些纯表现的地图(因此也可以排除纯表现的Actor),可以仅客户端加载。还有就是,NPC随用随刷、移动运算复杂度降低,等等,取决于游戏需求。

许多都是个人印象,不能作数,仅供参考。
祝好运!
发表于 2021-12-3 22:07 | 显示全部楼层
其他答主已经说了,ds的确是最早从FPS游戏发展过来的模式。其同步的解决方案和MMO的方案完全不是一个东西,因为是为了解决不同问题产生的。
你要是卡牌游戏,服务器完全自己做一套,不用管客户端是ue还是unity,他们只管显示。
你要是做FPS,tps,那么多半服务器和客户端共享代码,因为需要各种客户端预测和回溯方法。基本是对延迟要求比较敏感游戏的统一解决方案。
你要做几个玩家一局的rts,大量单位需要同步,那么同步玩家输入并锁帧的方法就是不错的选择。
你要做mmo,那就是前后短分离,前端ue还是其他引擎,不重要。关键是你的服务器架构。最最简单的说,服务器要管理游戏世界的创建分配,ue通过任何网络协议(多半TCP)和服务器通信玩家操作,和玩家周围可见的实体同步。不同服务器框架会有不同方案,很多会有多个服务器分布式处理。
ue默认的ds模式,通常不是简单的国内前后端分离。FPS游戏所谓的后端,是指线上匹配,玩家的平台相关数据处理,一旦游戏开始,游戏的gameplay,不是后端系统,因此不存在分离。
这也是国外很多游戏分单机部分和联机部分的传统导致,联机部分可能最后几个月才开发或者外包其他组也是可能的。
发表于 2021-12-3 22:16 | 显示全部楼层
不管是dedicated server还是listen server,客户端代码与服务器端代码都是混合在一起的。本来客户端逻辑和服务器端逻辑也非水火不相容,可以共享大量的代码。所以单机和多人游戏模式能够同时实现,这比之前那种强行把两端逻辑分离来写的开发模式高效很多,不需要为此定义一大批网络同步消息,当然调试和团队协作也不方便。
发表于 2021-12-3 22:23 | 显示全部楼层
如果大型服务器的话可以先从基础的底层socket套接字开始写,这样容易掌控,而且修bug比较方便。其实服务器很简单的,就是客户端游戏app  和 你的主机电脑相通过套接字建立连接,互发短信,告诉对方要做啥,剩下的无非就是速度优化咯
发表于 2021-12-3 22:30 | 显示全部楼层
服务器还是跟之前那些一样使用 c++或者golang的游戏服务器。 无非就是一些 socket通信。可以学习kbengine。如果不是大型网游 用UE4官方的DS也可以。
发表于 2021-12-3 22:36 | 显示全部楼层
我个人是个独立开发者,没参加过什么游戏项目,就随便说说自己的看法,对于我自己的游戏,我是想用预编译的宏来判断是不是用在服务器上的代码,楼主应该学过c++懂我意思吧,预编译就是让编译器执行的代码,比方说#if dedicated server 就表示如果当前编译的目标平台是dedicated server的话,就把下面包含的代码编译到这个项目里。还有一个方案就是执行的时候用一个Is dedicated server来判断是否ds
发表于 2021-12-3 22:37 | 显示全部楼层
虚幻就是一个写射击游戏的引擎,所以自然需要在服务器跑相关的gameplay,才能比如说伤害的判定。这些要是分开写,意味着你要写两份一模一样的代码,并且跑得一模一样。
至于分工的话,一般写服务器的人管类似于匹配,排名这种。写gameplay的人也要负责把要在服务器跑的逻辑写好了,像一些产生粒子,这种表现的东西区分开来也就妥了。
发表于 2021-12-3 22:42 | 显示全部楼层
推荐个c++高并发商业级服务器教程干货,客户端有ue4和unity3d.有兴趣的看一看吧
https://www.aboutcg.org/courseDetails/869/introduce
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2025-5-15 04:09 , Processed in 0.227078 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表