3D 游戏的万人同屏技术详解(2)

2020-08-23 10:22:42 +08:00
 gantleman
全文地址
https://zhuanlan.zhihu.com/p/195059458

在<使用 redis 实现 5 万人同服的'相位技术'>中我介绍了基于九宫格和相位技术的空间管理技术。这里我们也要借鉴游戏服务器中“服务”的概念。可能有些同学没有接触过游戏服务器,对服务的概念不是很熟悉。服务可以看做是一个独立的线程环境。这个线程监听着一个消息队列。其它的服务可以发送消息给他。这种方式在服务器开发中的 go 语言,erlang 语言,skynet 框架中被广泛应用。消息队列保证了服务所创建的数据是私有并且多线程安全的,只能通过消息通讯的方式进行修改。服务的概念为多线程下使用数据的安全问题提供了保护。通过消息通讯建立了在多线程下的秩序。但这种方式在客户端使用的并不多。各种服务的框架也都是在服务器端使用的多。

客户端使用多线程开发管理 1 万多个线程将会是一场噩梦。而管理 1 万多个服务对技术水平要求也还是比较高的。针对客户端没有多线程的服务框架问题,我开发了 pelagia 框架。借用“服务”的概念来管理客户端多线程。通过内嵌 kv 数据库和预判以及服务私有数据的概念彻底消灭多线程死锁和依赖的问题。因为只有解决多线程的安全问题。才能进一步思考如何优化通信和计算以及存储的平衡问题。安全问题不解决所有的优化问题就会是空中楼阁。

全文地址
https://zhuanlan.zhihu.com/p/195059458
23861 次点击
所在节点    推广
129 条回复
crclz
2020-08-30 08:08:58 +08:00
服务端渲染,传视频过来
fireapp
2020-08-30 08:58:04 +08:00
刚会写 crud 的人都喜欢扯 n10k,100k,1wk,但没有几个知道 n 是啥东西。罗列堆积名词
楼主的万人同屏连群聊都算不上
gantleman
2020-08-30 11:10:12 +08:00
@crclz
@fireapp

即使有视频谁能保证不是作假呢?
单机的示例在这里,都是开源免费的哦。
https://github.com/surparallel/unity_example_of_pelagia/tree/master/3D_Ten_Thousand
第一,我希望中国在游戏领域能做出自己就大做,中国游戏人都努力几十年了,还在捡国外的剩饭太苦了。
第二,我的技术都是开源免费的,这样的探索无论对错都是在给后人铺路,错了可以节约大家的时间,您笑一笑可以少走弯路。
第三,您用我的技术赚钱了也不用给我一毛钱。您夸我也好,骂我也好我都不介意。要是骂我能把我骂出名了,我还要谢谢你呢。
danc
2020-08-30 22:00:09 +08:00
大佬别光纸上谈兵啊,来个实际的游戏让我们体验体验
gantleman
2020-08-30 23:51:01 +08:00
@danc 是的我也希望中国早日作出 3A 大做,一起加油吧。
colincat
2020-08-31 19:28:35 +08:00
@dogfeet 老哥懂行
colincat
2020-08-31 19:30:24 +08:00
万人同屏的话客户端需要做一些特效的过滤,没那么简单,哈哈,这个早都有人搞过了 https://blog.csdn.net/jiangguilong2000/article/details/59514646
dogfeet
2020-08-31 20:21:22 +08:00
在知乎上又看到了这篇文章。
多说几句,超大地图,AOI 这种,跟放不放 Redis 没啥关系。所谓的相位技术也这是场景分割的一种方式。数据不放 Redis 的原因是,场景中的计算本身就需要实时,放到 Redis 中还得要异步的读写,明明用了 Actor 模型将关联逻辑分割到一起降低了并发与同步的心智包袱,又引入一个外部缓存让计算变成异步的,带来的数据一致性的问题完全抵消了 Actor 模型的优势。大量的位置数据,AI,技能延时,技能范围伤害等实时的逻辑都依赖状态,这些状态放外部存储中逻辑写起来有多麻烦尚且不说,拆的这么细,性能风险很高。连 Actor 的拆分都是要考虑粒度的,状态提出去把场景服都搞成无状态实在不觉得收益在哪里(养成等玩法无状态倒是没啥问题)。
Actor 模型在游戏界中往往用 state full 的形式,场景不是简单的状态,而是 状态+计算。
像微软的
Orleans ( https://github.com/dotnet/orleans
与 EA 开源的
Orbit ( https://github.com/orbit/orbit
这种新型的 Virtual Actor 模型的框架,游戏场景的使用都是 state full 的形式。
redis 的优势,
集群,游戏已经场景逻辑上已经通过 Actor 分割了,用不上。Actor 分割出来的逻辑数据单元关联性要强的多了。
各种数据结构,性能有没有优势不说,放外部已经高了不少延时,最主要的是复杂点的数据,没法按场景服务计算式需要的结构,直接扔 Redis,最后必然带来一个转换的开销。
各种过期淘汰策略,这在场景服务中做完全没问题啊,业务逻辑中 timer 相关的东西多了去了,Redis 反而不够用。

示例中场景,交互性太弱了,角色与角色之间的交互太少,跟真实游戏的业务场景相差太大了啊

当然,说了这么多,都只是解决大场景,同场景的一些方式方法。
万人同屏这个不敢想,个人觉得,目前的硬件,最后无论用什么方式(除了 step lock )做到了万人同屏的效果,
我估计实时性肯定无法让玩家能感受到正常的游戏体验。
gantleman
2020-09-01 22:09:10 +08:00
@dogfeet 你提出了问题,却又回避了问题,风险很高有多高?有哪些风险?关联要强又强在哪,有哪些好处和坏处。我们不把问题都列出来,又怎么能得出结论说哪个好哪个坏呢?用 redis 做示例是因为好懂,接口简单。并且性能在单线程数据服务中是最快的。普通程序员用演员模型加数据库写的缓存服务不可能比 redis 更快。redis 只做位置存储服务,只有两个接口写入,读取。为了文章好懂我省略了空间管理服务。并且每个游戏在空间管理上都会有细节的不同。演员模型只是一个产品上的概念,对于技术来说只能当作辅助设计工具。因为操作系统和开发本身都没有这个概念。部分语言有这个概念,然而语言到微服务又有十万八千里。如你所说纯粹的演员模型会导致通信成本激增。极端情况为每个玩家每种功能都创建服务。一方面要维护激增的接口,一方面要维护激增的硬件。
dogfeet
2020-09-01 23:17:43 +08:00
@gantleman 前面已经举例了,场景中玩家释放范围技能,技能还分各种类型,与玩家当前的 Buffer 息息相关。想想你状态都放 Redis 逻辑怎么写? PVP 的时候,血量,Buffer,技能类型的触发逻辑还是要非常严谨的。2 人一起释放技能攻击第三方,第一个技能攻击到受击者触发一个被动 Buffer 并进入 CD,第二个技能攻击到受击者,但是被动已经 CD,不会触发。按你上面的状态都丢 Redis,先不说你那个取范围技能的所有受击方靠不靠谱,场景角色上挂的 Buffer 血量等等相关的数据不要太多,2 个技能,你要保证被动只触发一次都麻烦的很。这还只是众多技能中非常常见的一些需求。

前面说的都是场景相关的功能,场景,Scene 。什么九宫格,十字链表,相位啥的,都是应用到场景服务上的。
养成玩法就不说了,谁跟你说场景服务是每个玩家每种功能创建服务?创建 Actor 永远都是把相关的放一起,不怎么相关的分离开来的原则。 [连 Actor 的拆分都是要考虑粒度的]
dogfeet
2020-09-01 23:33:31 +08:00
@gantleman
还有,你说 [普通程序员用演员模型加数据库写的缓存服务不可能比 redis 更快]
当然,特指场景服务,多少人同屏本身服务端压力就是场景服务
场景服务一般做法是,状态直接在内存中,这个内存是 Actor 的 state,Actor 可以是一个完整的小场景,亦可以是一个大场景的一个区域,根据实际情况划分。
该区域类的玩家操作直接在该 Actor 中处理,状态就在这个 Actor 内存中,而且就是原生的数据结构。各种技能的计算就像在客户端写顺序代码一样,数据会有策略落地,但是逻辑都是在内存中完成,只有加载场景才有读的动作。

并不是你想的那种 CURD,一个请求过来从数据库或者其他缓存中拿一堆丢失了结构的数据,一顿操作然后再回写数据。
gantleman
2020-09-02 13:26:26 +08:00
@dogfeet 可能你没有写过游戏服务器,对游戏服务器的技术不太了解。redis 的异步读写每秒可以支持 10 万次,操作都是按毫秒级 ,技能释放是用户按秒级别的计算 。redis 操作再慢还能比用户的操作还慢?为什么你把完全不同量级的东西都能搅和在一起说。
CODEWEA
2020-09-03 12:22:06 +08:00
redis 不是瓶颈
mrdemonson
2020-09-03 12:35:24 +08:00
个人认为 redis 只能管数据持久化问题,和游戏逻辑不沾边,游戏的精髓是技能衔接和玩家与玩家的互动影响,1 万个人同屏单机刷怪,还没和 100 个人混战 pk 难度高
iceheart
2020-09-03 12:45:52 +08:00
@gantleman #19 这个计算有点问题
10M/10K = 1K
cs8425
2020-09-03 13:11:32 +08:00
@gantleman #52
抱歉啊老兄 看了你这回覆我反而觉得是你没写过 PvP 游戏伺服器...
毫秒级很厉害吗?
现在一堆游戏伺服 game tick 随便都是 60 100Hz
至少都要微秒甚至奈秒及才够用
拿极端点的 100Hz 说,
10ms 就要跑完所有计算
请问您的"毫秒级"是能跑几次?
反而是 @dogfeet #48 #50 #51 的叙述比较正确
ps.个人写过最高 12 人的 PvP 游戏 可以肯定都是直接对内存做计算&操作
gantleman
2020-09-03 13:47:04 +08:00
@cs8425 请问 10ms 就要跑完所有计算?是什么计算?数据有哪些?请问“个人写过最高 12 人的 PvP 游戏 可以肯定都是直接对内存做计算&操作”的 技术指标。内存,cpu,网络带宽占用多少?你说了很多,但我没看出来,为什么 12 人的 PVP 导致硬件不够用。
shenlanAZ
2020-09-03 14:00:16 +08:00
@gantleman #52
redis 并没有那么强

曾经做过 IoT 的项目 数据会经过 redis 做校验 后来发现 redis 负载太高了 就换了验证方式不走 redis 了。

当时是初期的测试阶段 数据远达不到 10 万次 /秒。

看下来 dogfeet 讲的更靠谱。
cs8425
2020-09-03 14:12:10 +08:00
@gantleman #57
老兄 你好像没搞清楚我想表达的点?
我只想说你#52 讲的
"redis 的异步读写每秒可以支持 10 万次,操作都是按毫秒级,技能释放是用户按秒级别的计算。redis 操作再慢还能比用户的操作还慢?为什么你把完全不同量级的东西都能搅和在一起说。"
这点有个的错误: redis 毫秒级对于 PvP 游戏是不够用的
一点都没提到"12 人 PvP 游戏有硬件不够用的问题"
麻烦您再看清楚一点...

10ms 跑完哪些东西, 这个部份其实 @dogfeet #50 就有点出来了啊
不是我想杠 只是觉得您好像只看关键字...

可能我叙述不太清楚
另外再补充一下,
我弄的这个 PvP(老)游戏,
属于 TPS 射击对战
您可以想成 OW 的 TPS 版, 但是技能、攻击判定更复杂...
根据手上的资料,
用户操作最慢也是 0.5 秒一次, 众数在 200~250ms 之间, 顶尖的大概是在 100ms 上下
若把攻击判定算进来, 100ms 5 次都不是不可能
跟您所谓的"秒级"差异蛮大的....
scar263
2020-09-03 17:57:57 +08:00
万人同屏和万人同服并不是一个概念,请不要混淆

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/700635

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX