当前位置: 首页 > news >正文

Unity 红点系统

首先明确一个,即红点系统的数据结构是一颗树,并且红点的数据结构的初始化需要放在游戏的初始化中,之后再是对应的红点UI侧的注册,对应的红点UI在销毁时需要注销对红点UI的显示回调注册,但是不销毁数据侧的红点注册

- 具体分布

1. ReddotNode 红点结点类,数据侧

在这里插入图片描述
红点结点类负责承载红点的数据关系,其中在_reddotCnt的数据改变时,判断和现有值是否相等,如果不相等,赋值的同时,调用UI更新的回调

2. 红点UI类,表现侧

在这里插入图片描述
这里设计的是一个红点表现的抽象基类,因为红点的表现可能有多种多样,比如最直接的一个红色的点,或者是显示数字的红点,或者其他,那么对应的红点类型只需要继承这个类,然后实现各自的ReddotCallback就行了
在SubReddot方法中isCallImmediate参数用来判断是否需要在UI注册时立马调用一次回调,一般来说,在UI注册时,默认需要调用一次来判断是否需要显示红点,所以这里默认是true,这样的话,当重新回到某个UI面板时,重走一遍初始化注册时,会自动调一次红点显示判断

3. 具体红点类型

在这里插入图片描述
这里举了个例子,这是一个直接显示,隐藏的红点类型,所以只需要重写ReddotCallback,在内部判断红点计数,控制UI的显示隐藏就好

4. 红点树管理类

在这里插入图片描述
既然是管理类所以这个类被设计为一个单例类
在这个类的设计中,在查找方法中不设置创建的部分,因为之前参考某些红点框架,在查找不到时会去主动创建,但这里没有这么做,但在设置红点时,存在查找的部分
对于改变红点计数方法,其传入的数字是一个增量,是可正可负的,因为有的时候是减红点数,有的时候是加红点数,这个时候就可以传入-1或+1,如果当前结点的红点数加上增量 < 0,说明超出了范围,那么手动将增量设置为负的当前结点红点数,这样保证了即使超出范围,最后得到的值是0
并且在这里一开始是用的SetReddots方法,即设置,因为当想要改变一个红点的计数时,说明已经要用到这个结点,那么没有的话一定要创建出来,如果有的话,刚好直接查找就好
之后遍历这条路径上的每一个结点,将增量加上

- 具体使用

1. 邮件面板主页

public class Mail : MonoBehaviour{public Button mailButton;public GameObject mailPanel;public GameObject mailContent;public ReddotView reddotView;public GameObject mailTab;public GameObject Tab;public List<Button> tabs = new List<Button>();void Awake(){mailButton = GetComponent<Button>();mailButton.onClick.AddListener(OnMailButtonClick);//ReddotTree.Instance.SetReddots("Mail");InitMailData();reddotView.SubReddot("Mail");// var node = ReddotTree.Instance.SearchNode("Mail");// if(node.ReddotCnt > 0)// {//     reddotView.ReddotCallback(node);// }}void OnMailButtonClick(){for (int i = 0; i < 3; i++){var tab = Instantiate(mailTab, Tab.transform.Find("Viewport/Content")).GetComponent<MailTab>();var index = i;tab.Init("Mail/Tab" + index);tab.GetComponent<Button>().onClick.AddListener(() => OnTabClick("Tab" + index));}OnTabClick("Tab0");}public void OnTabClick(string tabName){var content = mailPanel.transform.Find("Viewport/Content");for (int i = 0; i < content.childCount; i++){Destroy(content.GetChild(i).gameObject);}for (int i = 0; i < 5; i++){var newMail = Instantiate(mailContent, mailPanel.transform.Find("Viewport/Content")).GetComponent<MailContent>();newMail.transform.SetAsLastSibling();var index= i;var path = "Mail/" + tabName + "/" + index;newMail.Init(path, tabName);}}/// <summary>/// 初始化红点数据/// </summary>public void InitMailData(){for (int i = 0; i < 3; i++){var path = "Mail/Tab" + i;for (int j = 0; j < 5; j++){var mailPath = path + "/" + j;ReddotTree.Instance.ChangeReddotCnt(mailPath, 1);}}}public void OnDestroy(){reddotView.UnSubReddot("Mail");}}

这是一个模拟邮件主面板的类,其初始化红点数据的方法写在了InitMailData中
在这里插入图片描述
这里直接使用了ChangeReddotCnt方法,在查找不到的时候直接设置红点结点数据,这个方法会在面板初始化的时候调用
在这里插入图片描述
可以看到,在数据初始化之后,此面板才注册了自身节点

在这里插入图片描述
注意在OnDestroy方法中需要注销对于红点UI的注册

具体结构如下
在这里插入图片描述
可以看到红点的UI默认是没有激活的

2. 邮件侧边栏

public class MailTab : MonoBehaviour
{public ReddotView reddotView;public string path;public void Init(string path){reddotView.SubReddot(path);this.path = path;// var node = ReddotTree.Instance.SearchNode(path);// if(node.ReddotCnt > 0)// {//     reddotView.ReddotCallback(node);// }}public void OnDestroy(){reddotView.UnSubReddot(path);}
}

这里只需要在初始化的时候注册红点就行,因为红点数据已经在一开始初始化了,同时OnDestroy的时候需要取消注册
在这里插入图片描述

3. 邮件条目

public class MailContent : MonoBehaviour{public ReddotView reddotView;public Button contentButton; public Button deleteButton;public string path;public Text contentText;public void Init(string path, string content){this.path = path;reddotView.SubReddot(path);// var node = ReddotTree.Instance.SearchNode(path);// if(node.ReddotCnt > 0)// {//     reddotView.ReddotCallback(node);// }//ReddotTree.Instance.ChangeReddotCnt(path, 1);contentText.text = content;}void Awake(){contentButton.onClick.AddListener(OnContentButtonClick);deleteButton.onClick.AddListener(OnDeleteButtonClick);}public void OnContentButtonClick(){ReddotTree.Instance.ChangeReddotCnt(path, -1);}public void OnDeleteButtonClick(){ReddotTree.Instance.ChangeReddotCnt(path, -1);//ReddotTree.Instance.UnSubReddot(path);Destroy(gameObject);}void OnDestroy(){//ReddotTree.Instance.ChangeReddotCnt(path, -1);//ReddotTree.Instance.UnSubReddot(path);reddotView.UnSubReddot(path);}}

同样是在初始化时注册,销毁时注销
在这里插入图片描述

4. 效果

在这里插入图片描述

相关文章:

  • 06.three官方示例+编辑器+AI快速学习webgl_animation_skinning_additive_blending
  • C++23 views::repeat (P2474R2) 深入解析
  • Redis BigKey 问题是什么
  • Android Canvas API 详细说明与示例
  • Android Native 函数 Hook 技术介绍
  • 飞蛾扑火算法matlab实现
  • 【leetcode】《BFS扫荡术:如何用广度优搜索征服岛屿问题》
  • 左右括号的最小处理次数
  • 深入了解linux系统—— 自定义shell
  • 《智能网联汽车 自动驾驶功能道路试验方法及要求》 GB/T 44719-2024——解读
  • ES常识5:主分词器、子字段分词器
  • Nodejs核心机制
  • 支持selenium的chrome driver更新到136.0.7103.92
  • 【Java EE初阶 --- 多线程(初阶)】线程安全问题
  • 百度AI战略解析:文心一言与自动驾驶的双轮驱动
  • Hibernate 性能优化:告别慢查询,提升数据库访问性能
  • 基于 PostgreSQL 的 ABP vNext + ShardingCore 分库分表实战
  • 使用FastAPI和React以及MongoDB构建全栈Web应用05 FastAPI快速入门
  • 红黑树(C++)
  • A1062 PAT甲级JAVA题解 Talent and Virtue
  • 脑血管支架:救命神器还是定时炸弹?听听医生的大实话
  • 中美瑞士会谈后中国会否取消矿产出口许可要求?外交部回应
  • 干部任职公示:陕西宁强、镇安两县县长拟进一步使用
  • 牛市早报|中美经贸高层会谈达成重要共识,取得实质性进展
  • 耿军强任陕西延安市领导,此前任陕西省公安厅机场公安局局长
  • 首映丨纪录电影《滚烫年华》:献给所有奋斗者