dfgxcvbcv
V2EX  ›  数据库

游戏中每隔 xx 分钟回复一格体力 数据库一般是怎么存储的?

  •  1
     
  •   dfgxcvbcv · Jul 8, 2022 · 7760 views
    This topic created in 1591 days ago, the information mentioned may be changed or developed.

    不太可能每分钟都遍历一次体力没满的用户吧

    37 replies  •  2022-07-10 23:28:44 +08:00
    joesonw
    joesonw
    Jul 8, 2022 via iPhone
    1
    1 ,数据一般是在内存里,然后落地到数据库的
    2 ,有用时间轮的,有每次请求检查上次更新的
    3 ,离线用户是登录的时候计算
    elioti
    elioti
    Jul 8, 2022
    2
    那就查询的时候更新呗
    banmuyutian
    banmuyutian
    Jul 8, 2022
    3
    盲猜延时消费消息?
    MoYi123
    MoYi123
    Jul 8, 2022
    4
    和令牌桶一样的做法啊.
    ranleng
    ranleng
    Jul 8, 2022❤️1
    5
    上一次恢复的时间,当前时间,每恢复 1hp 的时间, 就能算出来了。
    算完之后更新下上一次恢复的时间就行了
    fanyingmao
    fanyingmao
    Jul 8, 2022
    6
    现在就在写体力恢复的代码,就更查询时更新,数据库存一个时间和当前体力值,查询就对比当前时间和存的时间差多少,恢复多少体力,然后在把时间加上恢复体力*单位时间。
    wfhtqp
    wfhtqp
    Jul 8, 2022
    7
    只存储剩余体力以及上次消耗体力的时间,下次消耗的时候计算是否满足并更新数据。前端直接根据上次体力计算显示当前体力
    libook
    libook
    Jul 8, 2022❤️1
    8
    没做过游戏,只是有个脑洞,尽可能避免定时任务。

    记录上一次查询时间以及同时计算出来的体力值,活跃的用户每次来请求体力值的时候用上一次体力值与上一次到现在的时间长度来算涨多少体力值,超过体力上限就设为上限值,然后把新算的体力值和当前时间记录下来。性能和 PV 有关,和总用户数量无关。
    xianyv
    xianyv
    Jul 8, 2022
    9
    unity 的话有 Time 类可以计算时间间隔,或者使用协程间隔时间
    ahill
    ahill
    Jul 8, 2022
    10
    当前体力=当前时间- 上限范围内使用体力总数
    所以不需要记录当前体力,只需要记录 160*8min 内每次使用体力的时间和数量即可。最多是 160/20=8 条记录
    登陆的时候查询计算一次之后就在客户端计算,扣体力的时候后台校验一下
    IssacTomatoTan
    IssacTomatoTan
    Jul 8, 2022❤️1
    11
    体力值 +1 是游戏客户端根据人物状态自己展示 + - 的,不和服务端交流。

    服务端负责存下最后一次对体力值的修改,当游戏客户端发起请求说有人砍了我一刀我死了没呀?服务端就获取最后体力修改的时间,来计算到当前时间应有的体力值,然后计算这一刀的减去值,记录下最新的体力值,返回客户端死没死。
    mango88
    mango88
    Jul 8, 2022
    12
    数据库存上一次恢复时间,算的时候,
    min( (当前时间 - 上一次恢复时间) / 恢复一点体力需要的时间 + 当前剩余体力, 体力上限)
    yolee599
    yolee599
    Jul 8, 2022 via Android
    13
    存一个时间戳,用时更新
    v23x
    v23x
    Jul 8, 2022
    14
    这种东西就直接按时间加上去就好了呀....用户什么时候离线的这些全都是有的
    churchill
    churchill
    Jul 8, 2022
    15
    @IssacTomatoTan 那我找到这个发请求的方法 jump 掉 不就无敌了吗
    keenkiller
    keenkiller
    Jul 8, 2022 via Android
    16
    异步落库常规操作

    没听说过服务器回档么?
    rekulas
    rekulas
    Jul 8, 2022
    17
    时间相减即可计算出来,很简单
    升级版问题:facebook 是如何推送用户消息的,要知道头部用户一个贴可能要推送给上千万人,而每个用户可能关注了数百个甚至上千个其他用户
    weidaizi
    weidaizi
    Jul 8, 2022❤️1
    18
    像体力这种一般不落库,在追求速度的游戏当中(第一人称射击类,即使战略类)基本都是客户端自己算,服务器为了反外挂,会落一些数据到文件而不是数据库。MMORPG 类型的,我早年做游戏的时候,有服务器算的,也有客户端算的,但是也都不落库。一般需要落库的是一些等级,充值以及装备呀之类的
    Martens
    Martens
    Jul 8, 2022
    19
    服务器记一个时间戳,查询时更新
    客户端登录时同步,自己维护
    moen
    moen
    Jul 9, 2022
    20
    我曾经玩过的一个手游就是记录某个时刻和当时的体力值,下面是客户端反编译的代码相关的部分:
    ```
    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);
    }
    }
    ```
    nightwitch
    nightwitch
    Jul 9, 2022 via Android
    21
    只是内存里的一个 actor ,不会落库,客户端自行计算。为了反作弊服务端可能会采样记录一些信息。
    FakNoCNName
    FakNoCNName
    Jul 9, 2022
    22
    以前做过游戏,当时的逻辑是:

    1. 玩家上线时:把数据从库加载到内存
    2. 玩家在线时:用户基本数据在内存里面,正面状态( buff )、负面状态( debuff )实时计算并修改内存的值。
    2.1 触发式更新:当玩家参加活动、做任务时,每次开始、结束写一次库。
    2.2 其它累死 2.1 的场景,也使用触发式更新
    3. 玩家掉线时:(不论什么原因掉线)触发写库操作
    4. 服务器故障恢复:多节点组集群、使用 redis 做缓存(还会引入中间件故障恢复等问题,尽量少用)

    注:
    1~3 能解决大部分问题,这里采用触发式更新而不是定时(或时间轮)可以:避免 io 密集操作、玩家数据和数据库数据操作异步(偶尔遇到瓶颈也允许阻塞一小段时间)、保证玩家关键时刻的关键数据得以保存。

    玩家的行为是随机的,哪怕都在做活动,大多数情况也比时间轮随机,玩家多的时候时间轮压力也不小。
    FakNoCNName
    FakNoCNName
    Jul 9, 2022
    23
    所以你说的回血,不论前后端很可能是在内存中计算,在一个战斗节点或者战斗开始(结束)的时候存一次库。当然定时保存也是可能的。
    lscho
    lscho
    Jul 9, 2022
    24
    研究过外挂的应该都知道,血量 /体力 /攻击力等值一般都是登录的时候初始化到本地内存中的。。。然后战斗结算 /任务结算的时候才会与服务端通讯。

    当然有反作弊系统的话,即使不结算也会随机检测一下,数值不对就踢下线。
    nekochyan
    nekochyan
    Jul 9, 2022
    25
    体力这个肯定是前端向后端查询的时候才实时更新,然后其他时间前端起一个定时器去计算倒计时、什么时候恢复之类的
    dabaibai
    dabaibai
    Jul 9, 2022
    26
    上线才会处理
    x86
    x86
    Jul 9, 2022 via iPhone
    27
    本地内存中计算的,你看看那些锁血之类的修改差不多都一个原理
    Exdui
    Exdui
    Jul 9, 2022
    28
    @rekulas 粉丝登录 facebook 之后,查询一下有没有给他推送的消息?
    还是博主发帖时候,顺便把内容推送给所有关注的粉丝?
    junwind
    junwind
    Jul 9, 2022
    29
    游戏中一般是存在内存数据库中的,定期落地, 可以根据实际用的语言,框架, 比如 workerman 可以用定时器,或者定时任务来处理, 更新后推送一下到前端即可
    bruce0
    bruce0
    Jul 9, 2022
    30
    数据都在内存里,每次修改数据会同步到数据库, 像这种每小时恢复多少的, 一般都是记录一个时间, 比如上次恢复的时间戳, 每次获取数据的时候, 计算一下当前应该恢复到多少. 也有一些特殊的情况, 需要用一个定时器, 定时计算的, 这种情况非常少了
    Torpedo
    Torpedo
    Jul 9, 2022
    31
    为啥不用定时器啊,这不很正常么。这种类似的模型,编程语言里不就有,比如 js
    dfgxcvbcv
    dfgxcvbcv
    OP
    Jul 9, 2022
    32
    @Torpedo #31 用定时器玩家下线后怎么办?
    Torpedo
    Torpedo
    Jul 9, 2022
    33
    @dfgxcvbcv 这不是典型的用了事件,记得清除副作用么
    yyt6801
    yyt6801
    Jul 9, 2022 via Android
    34
    中间件??? 这种数据不会和数据库直接交互吧,都是在内存中
    hhjswf
    hhjswf
    Jul 9, 2022
    35
    @Exdui 一般都是推拉结合吧
    Jokerbj
    Jokerbj
    Jul 10, 2022
    36
    unity 或者虚幻里面可以加个触发功能,拿时间记一下,到时间直接自动触发一下
    d29107d
    d29107d
    Jul 10, 2022 via Android
    37
    @dfgxcvbcv 下线时记录时间戳,上线时再取时间戳,然后就可以计算出这个时间段内得到的体力
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   885 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 99ms · UTC 21:42 · PVG 05:42 · LAX 13:42 · JFK 16:42
    ♥ Do have faith in what you're doing.