[Unity]红点系统

参考大佬的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);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_46472622/article/details/131313562