首先明確一個,即紅點系統的數據結構是一顆樹,并且紅點的數據結構的初始化需要放在游戲的初始化中,之后再是對應的紅點UI側的注冊,對應的紅點UI在銷毀時需要注銷對紅點UI的顯示回調注冊,但是不銷毀數據側的紅點注冊
- 具體分布
1. ReddotNode 紅點結點類,數據側
紅點結點類負責承載紅點的數據關系,其中在_reddotCnt的數據改變時,判斷和現有值是否相等,如果不相等,賦值的同時,調用UI更新的回調
2. 紅點UI類,表現側
這里設計的是一個紅點表現的抽象基類,因為紅點的表現可能有多種多樣,比如最直接的一個紅色的點,或者是顯示數字的紅點,或者其他,那么對應的紅點類型只需要繼承這個類,然后實現各自的ReddotCallback就行了
在SubReddot方法中isCallImmediate參數用來判斷是否需要在UI注冊時立馬調用一次回調,一般來說,在UI注冊時,默認需要調用一次來判斷是否需要顯示紅點,所以這里默認是true,這樣的話,當重新回到某個UI面板時,重走一遍初始化注冊時,會自動調一次紅點顯示判斷
3. 具體紅點類型
這里舉了個例子,這是一個直接顯示,隱藏的紅點類型,所以只需要重寫ReddotCallback,在內部判斷紅點計數,控制UI的顯示隱藏就好
4. 紅點樹管理類
既然是管理類所以這個類被設計為一個單例類
在這個類的設計中,在查找方法中不設置創建的部分,因為之前參考某些紅點框架,在查找不到時會去主動創建,但這里沒有這么做,但在設置紅點時,存在查找的部分
對于改變紅點計數方法,其傳入的數字是一個增量,是可正可負的,因為有的時候是減紅點數,有的時候是加紅點數,這個時候就可以傳入-1或+1,如果當前結點的紅點數加上增量 < 0,說明超出了范圍,那么手動將增量設置為負的當前結點紅點數,這樣保證了即使超出范圍,最后得到的值是0
并且在這里一開始是用的SetReddots方法,即設置,因為當想要改變一個紅點的計數時,說明已經要用到這個結點,那么沒有的話一定要創建出來,如果有的話,剛好直接查找就好
之后遍歷這條路徑上的每一個結點,將增量加上
- 具體使用
1. 郵件面板主頁
public class Mail : MonoBehaviour{public Button mailButton;public GameObject mailPanel;public GameObject mailContent;public ReddotView reddotView;public GameObject mailTab;public GameObject Tab;public List<Button> tabs = new List<Button>();void Awake(){mailButton = GetComponent<Button>();mailButton.onClick.AddListener(OnMailButtonClick);//ReddotTree.Instance.SetReddots("Mail");InitMailData();reddotView.SubReddot("Mail");// var node = ReddotTree.Instance.SearchNode("Mail");// if(node.ReddotCnt > 0)// {// reddotView.ReddotCallback(node);// }}void OnMailButtonClick(){for (int i = 0; i < 3; i++){var tab = Instantiate(mailTab, Tab.transform.Find("Viewport/Content")).GetComponent<MailTab>();var index = i;tab.Init("Mail/Tab" + index);tab.GetComponent<Button>().onClick.AddListener(() => OnTabClick("Tab" + index));}OnTabClick("Tab0");}public void OnTabClick(string tabName){var content = mailPanel.transform.Find("Viewport/Content");for (int i = 0; i < content.childCount; i++){Destroy(content.GetChild(i).gameObject);}for (int i = 0; i < 5; i++){var newMail = Instantiate(mailContent, mailPanel.transform.Find("Viewport/Content")).GetComponent<MailContent>();newMail.transform.SetAsLastSibling();var index= i;var path = "Mail/" + tabName + "/" + index;newMail.Init(path, tabName);}}/// <summary>/// 初始化紅點數據/// </summary>public void InitMailData(){for (int i = 0; i < 3; i++){var path = "Mail/Tab" + i;for (int j = 0; j < 5; j++){var mailPath = path + "/" + j;ReddotTree.Instance.ChangeReddotCnt(mailPath, 1);}}}public void OnDestroy(){reddotView.UnSubReddot("Mail");}}
這是一個模擬郵件主面板的類,其初始化紅點數據的方法寫在了InitMailData中
這里直接使用了ChangeReddotCnt方法,在查找不到的時候直接設置紅點結點數據,這個方法會在面板初始化的時候調用
可以看到,在數據初始化之后,此面板才注冊了自身節點
注意在OnDestroy方法中需要注銷對于紅點UI的注冊
具體結構如下
可以看到紅點的UI默認是沒有激活的
2. 郵件側邊欄
public class MailTab : MonoBehaviour
{public ReddotView reddotView;public string path;public void Init(string path){reddotView.SubReddot(path);this.path = path;// var node = ReddotTree.Instance.SearchNode(path);// if(node.ReddotCnt > 0)// {// reddotView.ReddotCallback(node);// }}public void OnDestroy(){reddotView.UnSubReddot(path);}
}
這里只需要在初始化的時候注冊紅點就行,因為紅點數據已經在一開始初始化了,同時OnDestroy的時候需要取消注冊
3. 郵件條目
public class MailContent : MonoBehaviour{public ReddotView reddotView;public Button contentButton; public Button deleteButton;public string path;public Text contentText;public void Init(string path, string content){this.path = path;reddotView.SubReddot(path);// var node = ReddotTree.Instance.SearchNode(path);// if(node.ReddotCnt > 0)// {// reddotView.ReddotCallback(node);// }//ReddotTree.Instance.ChangeReddotCnt(path, 1);contentText.text = content;}void Awake(){contentButton.onClick.AddListener(OnContentButtonClick);deleteButton.onClick.AddListener(OnDeleteButtonClick);}public void OnContentButtonClick(){ReddotTree.Instance.ChangeReddotCnt(path, -1);}public void OnDeleteButtonClick(){ReddotTree.Instance.ChangeReddotCnt(path, -1);//ReddotTree.Instance.UnSubReddot(path);Destroy(gameObject);}void OnDestroy(){//ReddotTree.Instance.ChangeReddotCnt(path, -1);//ReddotTree.Instance.UnSubReddot(path);reddotView.UnSubReddot(path);}}
同樣是在初始化時注冊,銷毀時注銷