前言
一直想整理一下项目的红点设计,学习了大佬的文章【放牛的星星:Unity手游实战:从0开始SLG——独立功能扩展(三)用树实现客户端红点系统】,趁热整理一下我们项目的红点设计。
小曾也是第一次比较完整地经历整个项目,听大哥们说,手游制作游戏两大毒瘤:新手引导,红点系统。这个2个功能都是我们项目的王大帅哥写的,用的配置表实现,比较灵活,看着很舒服,想说整理一下,分享给大家。
今天先整理一下红点系统。由于我们项目的业务都写在lua层,所以实现都是lua。
2020.10.24 自己经历了一下红点的开发,踩了一些坑,继续总结跟大家分享。
先po一下大佬分析的红点系统分析,红点系统分为3个独立部分:结构层、驱动层、表现层
按照上面的3层管理设计。我们实现了3个脚本进行管理:
- RedDotModule 管理红点节点,组织红点关系的控制类
- RedTreeNode 红点节点抽象类
- RedDotItem 红点表现层对象
一、结构层:
设计这个红点系统的重中之重就是构建好这个结构关系,方便维护红点之间的层级关系,这个层级关系很明显是树结构,至于用什么去构建,有多种方式:
- ①可以用字符串分割:比如:main、main_mail、main_mail_system
- ②可以用配置表配置父节点。[mail] = {parent = main}、[system] = {parent = mail}
对于每个定义和红点类型,我们抽象了一个RedTreeNode红点节点类来管理,这个类负责维护红点的数量获取和数量变化管理。
二、驱动层:
- 业务在需要使用红点的地方,将生成的RedDotItem注册到红点系统里,让红点系统管理。
- 业务数据变化的时候,调用红点系统的接口,将红点数量push到红点系统里保存。【这里有个细节要注意一下:对于有层级关系的节点,只能设置叶子节点数量;非叶子节点数量是叶子节点红点数量之和】
- 数据变化的时候,红点系统判断是否需要状态变化,通知父节点。
上面这些管理都在红点系统RedDotModule类里实现,提供主要的红点注册RegisterRedDot和红点数量变化的Push方法,供业务调用。
优化:
- 后面在优化的时候,还引入了脏标记模式,解决同一帧多个子节点同时改变状态,将导致父节点进行额外的无用刷新的问题。
- + Debug Tree,将树结构以GO形式打印出来,方便调试
也就是说“ 红点的数量其实跟整套红点系统无关!”,它可以是来自服务器的协议通知,也可以是客户端自己传递的数据,或者从文件里读取出来的,总之红点系统本身只关注红点的产生和管理以及表现,不关心数据的来源。
我在实现的时候,不小心把数据部分耦合到红点系统内部,导致在维护的时候,想要重构,代价很大,所以 设计的时候要考虑好再下手。
三、表现层:
我们主界面的红点,有2种样式,一个是无数字的感叹号,一个是带数值的红点。2个红点可能同时存在一个节点上。这个比较简单,我们写个RedDotItem去管理就好,提供一个SetRedDotCount来控制显示和隐藏。
具体实现已上传GitHub:https://github.com/Aver58/Tools/tree/master/UnityProject/Assets/Scripts/RedDotSystem
参考:
Unity红点系统的实现
放牛的星星:Unity手游实战:从0开始SLG——独立功能扩展(三)用树实现客户端红点系统