1. 程式人生 > 其它 >基於樹結構實現的Unity紅點管理器

基於樹結構實現的Unity紅點管理器

基於 **樹結構** 實現的簡單紅點管理器,採用Unity+C#實現

簡述

基於 樹結構 實現的簡單紅點管理器,採用Unity+C#實現

核心邏輯是從 Unity手遊實戰:從0開始SLG——獨立功能擴充套件(三)用樹實現客戶端紅點系統 搬的,此demo做了部分封裝及備註說明,並詳細梳理了設計思路(紅點入坑√)

(其實目前網上大部分搜到的也是基於這篇,只不過除了作者外的文章都只是貼程式碼沒說明...)

專案地址:基於樹結構實現的Unity紅點管理器 - SouthBegonia

專案結構:

  • Assets/RedDotTutorial_1 // demo路徑
    • Prefabs // 演示demo的預製體
    • Scenes
      • RedDotTutorial_1.unity // 演示demo的場景
    • Scripts
      • RedDotCore // 紅點系統核心指令碼資料夾
      • ... // 演示demo的臨時業務指令碼

設計思路

將紅點管理器系統分為3層:結構層、驅動層、表現層

結構層

因為紅點的特性(多層級、多深度),因此一種做法是採用 來構造:

核心是通過紅點資料節點RedDotNode的 parent 和 rdChildrenDic 成員,實現樹結構關聯

備註:Mail節點指向Root節點採用虛線,是因為該例的所有紅點的路徑都是以Root為起點的(例如Root/Mail/System),但在業務開發上,基本不涉及Root節點(初始化和紅點路徑校驗時用得到),我們更關心的是第二層及其之後的節點

驅動層

如何驅動這個樹結構產生狀態變化,以及狀態變化之後如何將變化的行為通知到指定的表現層,在一定的程度上將資料和表現分離開

該過程的簡單理解:此紅點資訊變化->其RedDotNode資訊變化->通知其訂閱者->檢查父紅點RedDotNode資訊變化->父紅點資訊變化->...

SetRedDotNodeCallBack()Set() 方法就不詳細貼了,請檢視專案原始碼

表現層

在收到紅點變動的通知後,進行顯示變化處理(紅點樣式、紅點顯隱、紅點數、特效等),這層很獨立,看各自業務需求了

用法示例

比如有個紅點需求:主頁內有個郵箱按鈕(可顯示紅點),郵箱內又分為系統郵箱和隊伍郵箱(都可以顯示紅點)

首先配置紅點管理器RedDotSystem初始化的地方,正常業務應當放在遊戲初始化入口內,本demo就用到再初始化:

public static class ManagerComponent
{
    /// <summary>
    /// 紅點管理器
    /// </summary>
    private static RedDotSystem m_RedDotManager;
    public static RedDotSystem RedDotManager
    {
        get
        {
            //通常放在專案的初始化邏輯中,此處只是demo臨時寫法
            if (m_RedDotManager == null)
                m_RedDotManager = new RedDotSystem();
            return m_RedDotManager;
        }
    }
}

根據業務需求,新增3個紅點路徑到 E_RedDotDefineRedDotSystem.lstRedDotTreeList

/// <summary>
/// 紅點路徑定義
/// </summary>
public static class E_RedDotDefine
{
    /// <summary>
    /// 紅點樹的根節點
    /// </summary>
    public const string rdRoot = "Root";

    // ---------- 業務紅點 ----------
    public const string MailBox = "Root/Mail";
    public const string MailBox_System = "Root/Mail/System";
    public const string MailBox_Team = "Root/Mail/Team";
}

/// <summary>
/// 紅點系統
/// </summary>
public class RedDotSystem
{
    /// <summary>
    /// 紅點路徑的表(每次 E_RedDotDefine 新增完後此處也必須新增)
    /// </summary>
    private static List<string> lstRedDotTreeList = new List<string>
    {
        E_RedDotDefine.rdRoot,

        E_RedDotDefine.MailBox,
        E_RedDotDefine.MailBox_System,
        E_RedDotDefine.MailBox_Team,
    };
}

後就在業務邏輯內監聽紅點,本demo就用RedDotTutorial_1場景下的UI_xxx:

public class UI_xxx : MonoBehaviour
{
    public RedDotItem MailDot;

    void Start()
    {
        //註冊監聽紅點,正常業務應當放在 UI.OnInit 或 UI.OnOpen 中。記得在UI.OnClose 或 UI.OnDestroy時監聽置null
        ManagerComponent.RedDotManager.SetRedDotNodeCallBack(E_RedDotDefine.MailBox, MailCallBack);
        ManagerComponent.RedDotManager.SetRedDotNodeCallBack(E_RedDotDefine.MailBox_System, MailSystemCallBack);
        ManagerComponent.RedDotManager.SetRedDotNodeCallBack(E_RedDotDefine.MailBox_Team, MailTeamCallBack);
    }

    // 郵箱 紅點數變化回撥處理函式
    void MailCallBack(RedDotNode node)
    {
        MailDot.SetDotState(node.rdCount > 0, node.rdCount); //通知表現層
    }
}

最後就設定某紅點數的變化了:

//郵箱->系統 的紅點計數+1 按鈕點選事件
public void OnAddRdSystemBtnClick()
{
    int count = ManagerComponent.RedDotManager.GetRedDotCount(E_RedDotDefine.MailBox_System);
    ManagerComponent.RedDotManager.Set(E_RedDotDefine.MailBox_System, count + 1);
}

流程總結:

  1. 配置紅點系統初始化入口

  2. 新增紅點路徑資訊

  3. 業務模組監聽紅點變化 / 業務邏輯觸發紅點變化

優劣分析

  • 優勢:
    • 新加紅點不會引入新指令碼或配置檔案,配置方法簡單
    • 整體實現思路較為清晰簡潔(結構層、驅動層、表現層)
  • 劣勢:
    • 效能問題(基於string的紅點路徑在各方法內會頻繁執行String.Split()
    • 該結構相當於單一樹,在遊戲初始化時刻即構造完畢,但要是遇到需要動態新增紅點的需求呢?(再次重構紅點樹不大現實...)

參考文章