效果
学习了知乎大佬放牛的星星的红点系统。因为看到评论区有说不能动态添加移除红点所以在这基础上进行了改进。
原理比较简单,其实就是实现了一个从上到下的树状数据结构,通过给每个节点注册事件来实现不同的红点效果。如果没有数据结构基础建议先了解一下数据结构更方便理解。
代码下面是核心代码。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class RedPointSystem : MonoBehaviour
{
public delegate void OnPointNumChange(RedPointNode node); //红点变化通知
RedPointNode mRootNode; //红点树Root节点
static List redPointTreeList = new List //初始化红点树
{
//填入红点树信息
RedPointConst.main,
RedPointConst.mail,
RedPointConst.mailSystem,
RedPointConst.mailTeam,
RedPointConst.mailTeamInfo1,
RedPointConst.mailTeamInfo2,
};
///
/// 初始化红点树结构
///
public void InitRedPointTreeNode()
{
mRootNode = new RedPointNode(); //根节点
mRootNode.nodeName = RedPointConst.main; //设置根节点名称
foreach (var s in redPointTreeList)
{
AddNewRedPointToTree(s);
}
}
///
/// 遍历所有节点(从根节点开始)
///
public void Traverse()
{
TraverseTree(mRootNode);
}
///
/// 遍历该节点下的所有节点
///
///
void TraverseTree(RedPointNode node)
{
Debug.Log(node.nodeName);
if (node.dicChildren.Count == 0)
{
return;
}
foreach (var item in node.dicChildren.Values)
{
TraverseTree(item);
}
}
///
/// 在红点树中添加新节点
///
///
public void AddNewRedPointToTree(string strNode)
{
var node = mRootNode;
var treeNodeAy = strNode.Split('.'); //切割节点信息
if (treeNodeAy[0] != mRootNode.nodeName) //如果根节点不符合,报错并跳过该节点
{
Debug.LogError("RedPointTree Root Node Error:" + treeNodeAy[0]);
return;
}
if (treeNodeAy.Length > 1) //如果存在子节点
{
for (int i = 1; i 1) //如果存在子节点
{
//遍历获取最末目标节点
for (int i = 1; i 0)
//{
// if (parent.dicChildren.Count > 1)
// {
// RemoveNode(strNode, node, parent);
// return;
// }
// else if (!parent.parent)
// {
// RemoveNode(strNode, node, parent);
// return;
// }
// node = parent;
// parent = node.parent;
//}
}
else
{
Debug.LogError("You Are Trying To Delete Root!");
}
}
void RemoveNode(string strNode, RedPointNode node)
{
SetInvoke(strNode, 0);
node.parent.dicChildren.Remove(node.nodeName);
node.parent = null;
}
///
/// 设置红点回调(如果是移除又添加的需要重新绑定事件)
///
///
///
public void SetRedPointNodeCallBack(string strNode,RedPointSystem.OnPointNumChange callBack)
{
var nodeList = strNode.Split('.'); //分析树节点
if(nodeList.Length == 1)
{
if(nodeList[0] != RedPointConst.main)
{
//根节点不对
Debug.LogError("Get Wrong Root Node! Current Is " + nodeList[0]);
return;
}
}
var node = mRootNode;
//遍历传入key并获取最后一个节点添加回调
for (int i = 1; i 0);
Debug.Log("NodeName: " + node.nodeName + " PointNum:" + node.pointNum);
}
void MailTeamCallBack(RedPointNode node)
{
txtMailTeam.text = node.pointNum.ToString();
txtMailTeam.gameObject.SetActive(node.pointNum > 0);
Debug.Log("NodeName: " + node.nodeName + " PointNum:" + node.pointNum);
}
void MailSystemCallBack(RedPointNode node)
{
txtMailSystem.text = node.pointNum.ToString();
txtMailSystem.gameObject.SetActive(node.pointNum > 0);
Debug.Log("NodeName: " + node.nodeName + " PointNum:" + node.pointNum);
}
void MailTeamInfo1CallBack(RedPointNode node)
{
txtMailTeamInfo1.text = node.pointNum.ToString();
txtMailTeamInfo1.gameObject.SetActive(node.pointNum > 0);
Debug.Log("NodeName: " + node.nodeName + " PointNum:" + node.pointNum);
}
void MailTeamInfo2CallBack(RedPointNode node)
{
txtMailTeamInfo2.text = node.pointNum.ToString();
txtMailTeamInfo2.gameObject.SetActive(node.pointNum > 0);
Debug.Log("NodeName: " + node.nodeName + " PointNum:" + node.pointNum);
}
//移除指定红点
public void RemoveRedPoint()
{
rps.RemoveRedPointFromTree(RedPointConst.mailTeamInfo1);
rps.Traverse(); //打印树
}
//添加指定红点
public void AddRedPoint()
{
rps.AddNewRedPointToTree(RedPointConst.mailTeamInfo1);
rps.SetRedPointNodeCallBack(RedPointConst.mailTeamInfo1, MailTeamInfo1CallBack);
rps.SetInvoke(RedPointConst.mailTeamInfo1, 2);
rps.Traverse(); //打印树
}
}