Unity 通用红点系统

红点系统一般用多叉树实现。
树:

using System;
using System.Collections.Generic;
using UnityEngine;

[Serializable]
public class SGTreeNode
{
    
    
    [SerializeField]
    System.Object mData = null;
    [SerializeField]
    SGTreeNode mParent = null;
    [SerializeField]
    List<SGTreeNode> mChildren = null;
    [SerializeField]
    bool mIsLeaf = true;

    public bool IsLeaf {
    
     get {
    
     return mIsLeaf; } }
    public SGTreeNode Parent {
    
     get {
    
     return mParent; } }
    public List<SGTreeNode> Children {
    
     get {
    
     return mChildren; } }

    public SGTreeNode(System.Object data)
    {
    
    
        mChildren = new List<SGTreeNode>();
        mData = data;
    }

    public System.Object GetData() 
    {
    
    
        return mData;
    }

    public SGTreeNode SearchNode(Predicate<System.Object> compare)
    {
    
    
        if (compare.Invoke(mData))
        {
    
    
            return this;
        }
        else
        {
    
    
            SGTreeNode searchedNode = null;
            foreach (var item in mChildren)
            {
    
    
                if (compare.Invoke(item.mData))
                {
    
    
                    searchedNode = item;
                }
                else
                {
    
    
                    searchedNode = item.SearchNode(compare); 
                }
                if (searchedNode != null)
                {
    
    
                    break;
                }
            }
            return searchedNode;
        }
    }

    public SGTreeNode AddChild(SGTreeNode child)
    {
    
    
        this.mIsLeaf = false;
        child.mParent = this;
        mChildren.Add(child);
        return child;
    }
}

红点管理器:
以下红点系统树形结构参见初始化。

using SG.Utils;
using System;
using System.Collections.Generic;
using UnityEngine;

public enum RedPointType
{
    
    
    Null,
    Root,//红点系统根节点
    Task,//任务节点
    SignIn,//签到
    DailyTask, //每日任务
    DailyTaskItem, //每日具体项
    WeeklyTask,//每周任务
    WeeklyTaskItem,//每周任务具体项
    AchievementTask,//成就任务
    AchievementTaskItem,//成就任务具体项


}

public enum RedPointEvent
{
    
    
    RefreshRedPoint,
}

public class RedPointData
{
    
    
    public RedPointType mType = RedPointType.Null;
    public bool mIsShow = false;
    public Dictionary<string, bool> mExtDatas = new Dictionary<string, bool>();
    public int mRedCount = 0;

    public RedPointData(RedPointType type)
    {
    
    
        mType = type;
        mIsShow = false;
    }
}


public class RedPointManager2 :  MonoSingleton<RedPointManager2>
{
    
    
    [SerializeField]
    SGTreeNode mRootNode = null;

    /// <summary>
    /// 初始化红点系统
    /// </summary>
    public new void Init()
    {
    
    
        mRootNode = new SGTreeNode(new RedPointData(RedPointType.Root));
        
        var taskNode = mRootNode.AddChild(new SGTreeNode(new RedPointData(RedPointType.Task)));
        var signNode = taskNode.AddChild(new SGTreeNode(new RedPointData(RedPointType.SignIn)));
        var dailyTaskNode = taskNode.AddChild(new SGTreeNode(new RedPointData(RedPointType.DailyTask)));
        var weeklyTaskNode = taskNode.AddChild(new SGTreeNode(new RedPointData(RedPointType.WeeklyTask)));
        var achievementTaskNode = taskNode.AddChild(new SGTreeNode(new RedPointData(RedPointType.AchievementTask)));

        dailyTaskNode.AddChild(new SGTreeNode(new RedPointData(RedPointType.DailyTaskItem)));
        weeklyTaskNode.AddChild(new SGTreeNode(new RedPointData(RedPointType.WeeklyTaskItem)));
        achievementTaskNode.AddChild(new SGTreeNode(new RedPointData(RedPointType.AchievementTaskItem)));
    }

    /// <summary>
    /// 根据红点类型刷新红点是否显示。注:只能刷新叶子节点小红点数据
    /// </summary>
    /// <param name="redPointType"></param>
    /// <param name="isShow"></param>
    public void UpdateRedPoint(RedPointType redPointType, bool isShow)
    {
    
    
        var node = SearchNode(redPointType);

        if (node != null)
        {
    
    
            if (node.IsLeaf)
            {
    
    
                var data = node.GetData() as RedPointData;
                data.mIsShow = isShow;
                data.mRedCount = 1;
                UpdateParent(node.Parent);
                SendRefreshRedPointEvent(node);
            }
        }
    }

    /// <summary>
    /// 根据红点类型刷新红点是否显示。注:只能刷新叶子节点小红点数据
    /// </summary>
    /// <param name="redPointType"></param>
    /// <param name="extData">当前红点类型包含多条红点数据</param>
    public void UpdateRedPoint(RedPointType redPointType, Dictionary<string, bool> extData)
    {
    
    
        var node = SearchNode(redPointType);

        if (node != null)
        {
    
    
            if (node.IsLeaf)
            {
    
    
                var data = node.GetData() as RedPointData;
                var isShow = false;
                var showCount = 0;
                foreach (var item in extData)
                {
    
    
                    isShow = item.Value || isShow;
                    if (item.Value)
                    {
    
    
                        showCount++;
                    }
                    data.mExtDatas.Remove(item.Key);
                    data.mExtDatas[item.Key] = item.Value;
                }
                data.mIsShow = isShow;
                data.mRedCount = showCount;
                UpdateParent(node.Parent);
                SendRefreshRedPointEvent(node);
            }
        }
    }

    /// <summary>
    /// 获取红点数据信息
    /// </summary>
    /// <param name="redPointType"></param>
    /// <returns></returns>
    public RedPointData GetRedPointData(RedPointType redPointType)
    {
    
    
        var node = SearchNode(redPointType);
        if (node != null)
        {
    
    
            return node.GetData() as RedPointData;
        }
        else
        {
    
    
            return null;
        }
    }

    SGTreeNode SearchNode(RedPointType redPointType)
    {
    
    
        var node = mRootNode.SearchNode(new Predicate<object>(delegate (object nodeData) {
    
    
            RedPointData data = nodeData as RedPointData;
            if (data != null)
            {
    
    
                return data.mType == redPointType;
            }
            else
            {
    
    
                return false;
            }
        }));
        return node;
    }

    
    RedPointData GetNodeData(SGTreeNode node)
    {
    
    
        return node.GetData() as RedPointData;
    }

    void UpdateParent(SGTreeNode node)
    {
    
    
        if (node != null && !node.IsLeaf)
        {
    
    
            if (node.Children.Count > 0)
            {
    
    
                int redCount = 0;
                bool isShow = false;
                foreach (var item in node.Children)
                {
    
    
                    var dataTemp = GetNodeData(item);
                    isShow = isShow || dataTemp.mIsShow;
                    if (GetNodeData(item).mIsShow)
                    {
    
    
                        redCount = redCount + dataTemp.mRedCount;
                    }
                }
                var data = node.GetData() as RedPointData;
                data.mIsShow = isShow;
                data.mRedCount = redCount;
            }
            UpdateParent(node.Parent);
        }
    }

    void SendRefreshRedPointEvent(SGTreeNode node)
    {
    
    
        if (node != null)
        {
    
    
            GameEventMgr.Instance.SendEvent(RedPointEvent.RefreshRedPoint, new GameEventMgr.GameEventArgs()
            {
    
    
                data = node.GetData()
            });
            SendRefreshRedPointEvent(node.Parent);
        }
    }
}

使用示例:

 void TestRedPoint()
    {
    
    
        GameEventMgr.Instance.RemoveEvent(RedPointEvent.RefreshRedPoint, OnEventUpdateRedPoint);
        GameEventMgr.Instance.AddEvent(RedPointEvent.RefreshRedPoint, OnEventUpdateRedPoint);

        Debug.Log("=========UpdateRedPoint:SignIn");
        RedPointManager2.Instance.UpdateRedPoint(RedPointType.SignIn, true);
        
        Debug.Log("=========UpdateRedPoint:DailyTaskItem   1");
        RedPointManager2.Instance.UpdateRedPoint(RedPointType.DailyTaskItem, true);

        Debug.Log("=========UpdateRedPoint:DailyTaskItem   2");
        Dictionary<string, bool> mData = new Dictionary<string, bool>();
        mData["1000"] = true;
        mData["1001"] = true;
        mData["1002"] = false;
        RedPointManager2.Instance.UpdateRedPoint(RedPointType.DailyTaskItem, mData);
    }

    void OnEventUpdateRedPoint(AEventArgs arg)
    {
    
    
        var temp = arg as GameEventMgr.GameEventArgs;
        var data = temp.data as RedPointData;
       
        Debug.Log("===========TestEvent:" + LitJson.JsonMapper.ToJson(data));
    }

输出:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lcl20093466/article/details/126011431
今日推荐