参考大佬的lua 版本【游戏开发实战】手把手教你在Unity中使用lua实现红点系统(前缀树 | 数据结构 | 设计模式 | 算法 | 含工程源码)_unity红点系统_林新发的博客-CSDN博客
修改为c#版本,本人的仓库地址:
https://github.com/Zhou04191919/RedPointSystem.git
核心脚本:
RedPointNode.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RedPointNode
{
/// <summary>
/// 节点名
/// </summary>
public string name;
/// <summary>
/// 节点被经过的次数
/// </summary>
public int passCnt=0;
/// <summary>
/// 节点作为尾节点的次数
/// </summary>
public int endCnt = 0;
/// <summary>
///
/// </summary>
public int redpointCnt = 0;
public Dictionary<string, RedPointNode> children = new Dictionary<string, RedPointNode>();
public Dictionary<string, Action<int>> updateCb = new Dictionary<string, Action<int>>();
public RedPointNode(string name)
{
this.name = name;
this.passCnt = 0;
this.endCnt = 0;
this.redpointCnt = 0;
this.children = new Dictionary<string, RedPointNode>();
this.updateCb = new Dictionary<string, Action<int>>();
}
public static RedPointNode New(string name)
{
return new RedPointNode(name);
}
}
RedpointTree.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Design.Serialization;
using System.Xml.Linq;
using Unity.VisualScripting;
using UnityEngine;
public class RedpointTree
{
private RedPointNode root;
public Dictionary<string, string> NodeNames = new Dictionary<string, string>
{
{ "Root","Root"},
{ "ModelA","Root|ModelA"},
{ "ModelA_Sub_1 ","Root|ModelA|ModelA_Sub_1"},
{ "ModelA_Sub_2 ","Root|ModelA|ModelA_Sub_2"},
{ "ModelB ", "Root|ModelB"},
{ "ModelB_Sub_1 ","Root|ModelB|ModelB_Sub_1"},
{ "ModelB_Sub_2 ","Root|ModelB|ModelB_Sub_2"}
};
public RedpointTree()
{
root = new RedPointNode("Root");
}
public void Init()
{
this.root =new RedPointNode("Root");
构建前缀树
foreach (var name in NodeNames.Values)
{
this.InsertNode(name);
}
ChangeRedPointCnt(NodeNames["ModelA_Sub_1"], 1);
ChangeRedPointCnt(NodeNames["ModelA_Sub_2"], 1);
ChangeRedPointCnt(NodeNames["ModelB_Sub_1"], 1);
ChangeRedPointCnt(NodeNames["ModelB_Sub_2"], 1);
}
public void InsertNode(string name)
{
if (string.IsNullOrEmpty(name))
{
return;
}
if (SearchNode(name) != null)
{
Debug.Log("你已经插入了此节点" + name);
return;
}
RedPointNode node = root;
node.passCnt += 1;
string[] pathList = name.Split("|");
foreach (string path in pathList)
{
if (!node.children.ContainsKey(path))
{
node.children.Add(path, RedPointNode.New(path));
}
node = node.children[path];
node.passCnt = node.passCnt + 1;
}
node.endCnt = node.endCnt + 1;
}
/// <summary>
/// 查询节点是否在树中并返回节点
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public RedPointNode SearchNode(string name)
{
if (string.IsNullOrEmpty(name))
{
return null;
}
RedPointNode node = this.root;
string[] pathList = name.Split("|");
foreach (string path in pathList)
{
if (!node.children.ContainsKey(path))
{
return null;
}
node = node.children[path];
}
if (node.endCnt > 0)
{
return node;
}
return null;
}
/// <summary>
/// 删除某个节点
/// </summary>
/// <param name="name"></param>
public void DeleteNode(string name)
{
if (SearchNode(name) == null)
{
return;
}
RedPointNode node = this.root;
node.passCnt = node.passCnt - 1;
string[] pathList = name.Split("|");
foreach (string path in pathList)
{
RedPointNode childNode = node.children[path];
childNode.passCnt = childNode.passCnt - 1;
if (childNode.passCnt == 0)
{
// 如果该节点没有任何孩子,则直接删除
node.children.Remove(path);
return;
}
node = childNode;
}
node.endCnt = node.endCnt - 1;
}
/// <summary>
/// 修改节点的红点数
/// </summary>
/// <param name="name"></param>
/// <param name="delta"></param>
public void ChangeRedPointCnt(string name,int delta)
{
RedPointNode targetNode = SearchNode(name);
if(targetNode==null)
{
return;
}
if(delta<0&& targetNode.redpointCnt+delta<0)
{
delta = -targetNode.redpointCnt;
}
RedPointNode node = this.root;
string[] pathList = name.Split("|");
foreach (string path in pathList)
{
RedPointNode childNode = node.children[path];
childNode.redpointCnt = childNode.redpointCnt + delta;
node = childNode;
foreach (Action<int> cb in node.updateCb.Values)
{
cb?.Invoke(node.redpointCnt);
}
}
}
/// <summary>
/// 设置红点更新回调函数
/// </summary>
/// <param name="name"></param>
/// <param name="key"></param>
/// <param name="cb"></param>
public void SetCallBack(string name,string key,Action<int>cb)
{
RedPointNode node = SearchNode(name);
if (node == null)
{
return;
}
node.updateCb.Add(key, cb);
}
/// <summary>
/// 查询节点的红点数
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public int GetRedPointCnt(string name)
{
RedPointNode node = SearchNode(name);
if (node == null)
{
return 0;
}
return node.redpointCnt;
}
}
public class NodeNames
{
public const string Root = "Root";
public const string ModelA = "Root|ModelA";
public const string ModelA_Sub_1 = "Root|ModelA|ModelA_Sub_1";
public const string ModelA_Sub_2 = "Root|ModelA|ModelA_Sub_2";
public const string ModelB = "Root|ModelB";
public const string ModelB_Sub_1 = "Root|ModelB|ModelB_Sub_1";
public const string ModelB_Sub_2 = "Root|ModelB|ModelB_Sub_2";
public static List<string> NodeList = new List<string>() {
Root,ModelA,ModelA_Sub_1,ModelA_Sub_2,ModelB,ModelB_Sub_1,ModelB_Sub_2
};
}
应用:
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
public class GameHallPanel : MonoBehaviour
{
[SerializeField] Text txtRoot;
[SerializeField] Text txtModelA;
[SerializeField] Text txtModelA_1;
[SerializeField] Text txtModelA_2;
[SerializeField] Text txtModelB;
[SerializeField] Text txtModelB_1;
[SerializeField] Text txtModelB_2;
[SerializeField] Button txtRootBtn;
[SerializeField] Button txtModelABtn;
[SerializeField] Button txtModelA_1Btn;
[SerializeField] Button txtModelA_2Btn;
[SerializeField] Button txtModelBBtn;
[SerializeField] Button txtModelB_1Btn;
[SerializeField] Button txtModelB_2Btn;
[SerializeField] Button ReBtn;
[SerializeField] GameObject op;
[SerializeField] GameObject tp;
[SerializeField] GameObject ap;
[SerializeField] GameObject bp;
RedpointTree redpointTree;
void Start()
{
//redpointTree= new RedpointTree();
//redpointTree.Init();
//redpointTree.SetCallBack(redpointTree.NodeNames["Root"], "Root", redpointCnt =>
//{
// UpdateRedPoint(redpointCnt);
//});
op.SetActive(true);
tp.SetActive(false);
RegisterClickEvents();
CreateTree();
SetCallBack();
AddDate();
}
private void CreateTree()
{
redpointTree = new RedpointTree();
for (int i = 0; i < NodeNames.NodeList.Count; i++)
{
redpointTree.InsertNode(NodeNames.NodeList[i]);
}
}
private void RegisterClickEvents()
{
txtRootBtn.onClick.AddListener(()=> { op.SetActive(false);tp.SetActive(true); }); ;
ReBtn.onClick.AddListener(() => { op.SetActive(true); tp.SetActive(false); });
txtModelABtn.onClick.AddListener(() => { bp.SetActive(false); ap.SetActive(true); }) ;
txtModelA_1Btn.onClick.AddListener(()=> { redpointTree.ChangeRedPointCnt(NodeNames.ModelA_Sub_1, -1); });
txtModelA_2Btn.onClick.AddListener(() => { redpointTree.ChangeRedPointCnt(NodeNames.ModelA_Sub_2, -1); });
txtModelBBtn.onClick.AddListener(() => { bp.SetActive(true); ap.SetActive(false); }) ;
txtModelB_1Btn.onClick.AddListener(() => { redpointTree.ChangeRedPointCnt(NodeNames.ModelB_Sub_1, -1); });
txtModelB_2Btn.onClick.AddListener(() => { redpointTree.ChangeRedPointCnt(NodeNames.ModelB_Sub_2, -1); });
}
private void SetCallBack()
{
redpointTree.SetCallBack(NodeNames.Root, "Root", (redpointCnt) =>
{
ShowText(txtRoot, redpointCnt);
});
redpointTree.SetCallBack(NodeNames.ModelA, "ModelA", (redpointCnt) =>
{
ShowText(txtModelA, redpointCnt);
});
redpointTree.SetCallBack(NodeNames.ModelA_Sub_1, "ModelA_Sub_1", (redpointCnt) =>
{
ShowText(txtModelA_1, redpointCnt);
});
redpointTree.SetCallBack(NodeNames.ModelA_Sub_2, "ModelA_Sub_2", (redpointCnt) =>
{
ShowText(txtModelA_2, redpointCnt);
});
redpointTree.SetCallBack(NodeNames.ModelB, "ModelB", (redpointCnt) =>
{
ShowText(txtModelB, redpointCnt);
});
redpointTree.SetCallBack(NodeNames.ModelB_Sub_1, "ModelB_Sub_1", (redpointCnt) =>
{
ShowText(txtModelB_1, redpointCnt);
});
redpointTree.SetCallBack(NodeNames.ModelB_Sub_2, "ModelB_Sub_2", (redpointCnt) =>
{
ShowText(txtModelB_2, redpointCnt);
});
}
private void ShowText( Text text, int redpointCnt)
{
text.text = redpointCnt.ToString();
text.transform.parent.gameObject.SetActive(redpointCnt > 0);
}
private void AddDate()
{
redpointTree.ChangeRedPointCnt(NodeNames.ModelA_Sub_1, 1);
redpointTree.ChangeRedPointCnt(NodeNames.ModelA_Sub_2, 1);
redpointTree.ChangeRedPointCnt(NodeNames.ModelB_Sub_1, 1);
redpointTree.ChangeRedPointCnt(NodeNames.ModelB_Sub_2, 1);
}
}
文章评论