不太可能每分钟都遍历一次体力没满的用户吧
1
joesonw 2022-07-08 17:05:14 +08:00 via iPhone
1 ,数据一般是在内存里,然后落地到数据库的
2 ,有用时间轮的,有每次请求检查上次更新的 3 ,离线用户是登录的时候计算 |
2
elioti 2022-07-08 17:05:41 +08:00
那就查询的时候更新呗
|
3
banmuyutian 2022-07-08 17:05:47 +08:00
盲猜延时消费消息?
|
4
MoYi123 2022-07-08 17:05:50 +08:00
和令牌桶一样的做法啊.
|
5
ranleng 2022-07-08 17:12:49 +08:00 1
上一次恢复的时间,当前时间,每恢复 1hp 的时间, 就能算出来了。
算完之后更新下上一次恢复的时间就行了 |
6
fanyingmao 2022-07-08 17:14:45 +08:00
现在就在写体力恢复的代码,就更查询时更新,数据库存一个时间和当前体力值,查询就对比当前时间和存的时间差多少,恢复多少体力,然后在把时间加上恢复体力*单位时间。
|
7
wfhtqp 2022-07-08 17:15:10 +08:00
只存储剩余体力以及上次消耗体力的时间,下次消耗的时候计算是否满足并更新数据。前端直接根据上次体力计算显示当前体力
|
8
libook 2022-07-08 17:15:37 +08:00 1
没做过游戏,只是有个脑洞,尽可能避免定时任务。
记录上一次查询时间以及同时计算出来的体力值,活跃的用户每次来请求体力值的时候用上一次体力值与上一次到现在的时间长度来算涨多少体力值,超过体力上限就设为上限值,然后把新算的体力值和当前时间记录下来。性能和 PV 有关,和总用户数量无关。 |
9
xianyv 2022-07-08 17:17:55 +08:00
unity 的话有 Time 类可以计算时间间隔,或者使用协程间隔时间
|
10
ahill 2022-07-08 17:32:47 +08:00
当前体力=当前时间- 上限范围内使用体力总数
所以不需要记录当前体力,只需要记录 160*8min 内每次使用体力的时间和数量即可。最多是 160/20=8 条记录 登陆的时候查询计算一次之后就在客户端计算,扣体力的时候后台校验一下 |
11
IssacTomatoTan 2022-07-08 17:38:54 +08:00 1
体力值 +1 是游戏客户端根据人物状态自己展示 + - 的,不和服务端交流。
服务端负责存下最后一次对体力值的修改,当游戏客户端发起请求说有人砍了我一刀我死了没呀?服务端就获取最后体力修改的时间,来计算到当前时间应有的体力值,然后计算这一刀的减去值,记录下最新的体力值,返回客户端死没死。 |
12
mango88 2022-07-08 17:42:28 +08:00
数据库存上一次恢复时间,算的时候,
min( (当前时间 - 上一次恢复时间) / 恢复一点体力需要的时间 + 当前剩余体力, 体力上限) |
13
yolee599 2022-07-08 20:45:36 +08:00 via Android
存一个时间戳,用时更新
|
14
v23x 2022-07-08 20:48:59 +08:00
这种东西就直接按时间加上去就好了呀....用户什么时候离线的这些全都是有的
|
15
churchill 2022-07-08 21:09:33 +08:00
@IssacTomatoTan 那我找到这个发请求的方法 jump 掉 不就无敌了吗
|
16
tairan2006 2022-07-08 21:31:10 +08:00 via Android
异步落库常规操作
没听说过服务器回档么? |
17
rekulas 2022-07-08 21:41:40 +08:00
时间相减即可计算出来,很简单
升级版问题:facebook 是如何推送用户消息的,要知道头部用户一个贴可能要推送给上千万人,而每个用户可能关注了数百个甚至上千个其他用户 |
18
weidaizi 2022-07-08 21:57:26 +08:00 1
像体力这种一般不落库,在追求速度的游戏当中(第一人称射击类,即使战略类)基本都是客户端自己算,服务器为了反外挂,会落一些数据到文件而不是数据库。MMORPG 类型的,我早年做游戏的时候,有服务器算的,也有客户端算的,但是也都不落库。一般需要落库的是一些等级,充值以及装备呀之类的
|
19
Martens 2022-07-08 22:50:12 +08:00
服务器记一个时间戳,查询时更新
客户端登录时同步,自己维护 |
20
moen 2022-07-09 00:00:15 +08:00
我曾经玩过的一个手游就是记录某个时刻和当时的体力值,下面是客户端反编译的代码相关的部分:
``` public new int St { get { if (base.St >= SingletonInstance<UserService>.SharedInstance.MaxSt) { return base.St; } double num = (SingletonInstance<TimeService>.SharedInstance.ServerDateTime - base.StUpdatedAt).TotalSeconds / ServerConsts.HealStInterval.TotalSeconds; return Mathf.Min(SingletonInstance<UserService>.SharedInstance.MaxSt, base.St + (int)num); } } ``` |
21
nightwitch 2022-07-09 02:41:52 +08:00 via Android
只是内存里的一个 actor ,不会落库,客户端自行计算。为了反作弊服务端可能会采样记录一些信息。
|
22
FakNoCNName 2022-07-09 09:24:56 +08:00
以前做过游戏,当时的逻辑是:
1. 玩家上线时:把数据从库加载到内存 2. 玩家在线时:用户基本数据在内存里面,正面状态( buff )、负面状态( debuff )实时计算并修改内存的值。 2.1 触发式更新:当玩家参加活动、做任务时,每次开始、结束写一次库。 2.2 其它累死 2.1 的场景,也使用触发式更新 3. 玩家掉线时:(不论什么原因掉线)触发写库操作 4. 服务器故障恢复:多节点组集群、使用 redis 做缓存(还会引入中间件故障恢复等问题,尽量少用) 注: 1~3 能解决大部分问题,这里采用触发式更新而不是定时(或时间轮)可以:避免 io 密集操作、玩家数据和数据库数据操作异步(偶尔遇到瓶颈也允许阻塞一小段时间)、保证玩家关键时刻的关键数据得以保存。 玩家的行为是随机的,哪怕都在做活动,大多数情况也比时间轮随机,玩家多的时候时间轮压力也不小。 |
23
FakNoCNName 2022-07-09 09:28:14 +08:00
所以你说的回血,不论前后端很可能是在内存中计算,在一个战斗节点或者战斗开始(结束)的时候存一次库。当然定时保存也是可能的。
|
24
lscho 2022-07-09 09:48:45 +08:00
研究过外挂的应该都知道,血量 /体力 /攻击力等值一般都是登录的时候初始化到本地内存中的。。。然后战斗结算 /任务结算的时候才会与服务端通讯。
当然有反作弊系统的话,即使不结算也会随机检测一下,数值不对就踢下线。 |
25
nekochyan 2022-07-09 10:12:20 +08:00
体力这个肯定是前端向后端查询的时候才实时更新,然后其他时间前端起一个定时器去计算倒计时、什么时候恢复之类的
|
26
dabaibai 2022-07-09 10:59:25 +08:00
上线才会处理
|
27
x86 2022-07-09 11:07:29 +08:00 via iPhone
本地内存中计算的,你看看那些锁血之类的修改差不多都一个原理
|
28
Exdui 2022-07-09 11:10:05 +08:00
@rekulas 粉丝登录 facebook 之后,查询一下有没有给他推送的消息?
还是博主发帖时候,顺便把内容推送给所有关注的粉丝? |
29
junwind 2022-07-09 11:47:22 +08:00
游戏中一般是存在内存数据库中的,定期落地, 可以根据实际用的语言,框架, 比如 workerman 可以用定时器,或者定时任务来处理, 更新后推送一下到前端即可
|
30
bruce0 2022-07-09 11:51:51 +08:00
数据都在内存里,每次修改数据会同步到数据库, 像这种每小时恢复多少的, 一般都是记录一个时间, 比如上次恢复的时间戳, 每次获取数据的时候, 计算一下当前应该恢复到多少. 也有一些特殊的情况, 需要用一个定时器, 定时计算的, 这种情况非常少了
|
31
Torpedo 2022-07-09 16:10:38 +08:00
为啥不用定时器啊,这不很正常么。这种类似的模型,编程语言里不就有,比如 js
|
34
yyt6801 2022-07-09 20:30:01 +08:00 via Android
中间件??? 这种数据不会和数据库直接交互吧,都是在内存中
|
36
Jokerbj 2022-07-10 21:30:52 +08:00
unity 或者虚幻里面可以加个触发功能,拿时间记一下,到时间直接自动触发一下
|