最后更新于 .

游戏内小红点算是一个极其常用的功能了,之前在德州里面也有过实现。
然而之前的实现实在是乱七八糟,所以这次也是将其做了彻底的重写,并把方案跟大家分享一下。

我们将游戏内小红点可以分为三类:

  1. 服务器小红点-服务器自动清除

    比如,我们常见的每日任务,成长任务,活动等。
    以每日任务举例:
    当有任务奖励可以领取时,在每日任务按钮上就显示小红点。
    当任务奖励全部领取完毕后,小红点消失。

  2. 服务器小红点-客户端告知服务器清除

    比如,信箱功能,新好友通知,好友申请通知。
    以信箱举例:
    有新邮件,则信箱按钮就显示小红点。
    打开信箱后,如果信箱内分标签页,则判断标签页下的邮件列表,如果有新邮件,则在标签上显示小红点。
    当标签页打开之后,标签页上小红点消失。 当所有标签页的小红点都消失后,信箱按钮上的小红点消失

  3. 客户端小红点-客户端自己维护

    比如聊天功能。

    登录时,拉取所有未读消息,如果有消息的话,大厅聊天按钮需要显示小红点。
    之后,当收到新的好友消息的时候,大厅聊天按钮需要显示小红点。
    当点击聊天按钮进入具体的聊天页面时,每个有新消息的好友页签,需要显示小红点。
    当点击该页签时,小红点消失。
    当所有页签的小红点消失后,大厅聊天按钮的小红点消失。

接下里我们说一下具体的实现。

首先,所有服务器小红点的状态,在用户登录的时候,就应该返回。
所以我们在登录协议里面增加了一个red_points字段.

repeated int32 red_points = 1;

我们为每种小红点定义了一种类型,在red_points中即代表有小红点,否则代表没有。

而当进入游戏后,小红点的状态是可能动态变化的。所以我们需要定义一个主动下发的协议,通知小红点状态变化。

message EvtRedPointsChanged {
    map<int32, bool> map_red_points = 1;
}

最后,服务器端需要提供一个接口,供客户端主动清除小红点

message ReqClearRedPoints {
    repeated int32 red_points = 1;
}

这样,我们的基础准备工作就结束了。

接下来,就是具体的实现方法了。

  1. 服务器小红点-服务器自动清除

    服务器端再当状态发生改变时,就发出对应的信号,在信号处理函数中,计算新的red_points,之后下发EvtRedPointsChanged。
    这样,无论小红点是增加还是删除,都会通过EvtRedPointsChanged下发给客户端。

  2. 服务器小红点-客户端告知服务器清除

    以信箱为例。

    用户登陆后,假设信箱有小红点标识,于是用户打开信箱。
    此时,客户端向服务器请求信件列表,并缓存在本地,并与老的邮件列表做对比,检查每个标签页下是否有新增邮件。
    有新增邮件的标签页,需要显示小红点。
    当用户点击某个标签页时,将该标签页的小红点标记消失。
    如果所有标签页都没有小红点时,则信箱的整体小红点消失,并向服务器发送ReqClearRedPoints来清空小红点。

  3. 客户端小红点-客户端自己维护

    以聊天举例。

    首先所有的聊天消息都应该有一个绝对唯一的msg_id,并且服务器只会通知一次聊天消息,之后就会从服务器删除。
    包括登录后拉取的离线时收到的聊天消息也是如此,服务器返回之后,在服务器端就不再保存了。

    客户端收到消息后需要分room缓存在本地,这里的room是一个概念,比如群聊天就是群ID,和好友聊天就是好友的uid。
    并将收到新消息的room标记上小红点。
    之后点击进入该room时,就清除掉小红点。
    当所有room的小红点都清除掉之后,就清除掉大厅聊天按钮的小红点。

理论基本就是这样了。

具体实现的话,建议多使用redis,利用好redis的数据结构和自动过期特性,性能和可维护性都会高不少。

Pingbacks

Pingbacks已打开。

Trackbacks

引用地址

评论

  1. adrain

    adrain on #

    服务器不存储用户已读信件,仅靠客户端自己的缓存。
    在还有未读的情况下,即还没有请求服务器ReqClearRedPoints。
    客户端清掉缓存,或者卸载重新安装,
    重新登录,
    整体小红点还会有,标签页的小红点是哪个标签页的呢?

    Reply

    1. Dante

      Dante on #

      其实清缓存或者重装的概率还是比较低的,我的建议是所有页签都标记小红点,一般页签数也不会太多,用户都点一遍就可以了。

      Reply

发表评论