在现代游戏开发中,红点提示系统是一种常见且有效的用户交互方式,能够及时提示玩家需要关注的内容。本文将介绍一个基于Unity的红点系统通用框架的实现,并提出一些优化建议,以提高代码的性能和可维护性。
框架设计概述
该红点系统框架主要由三个核心部分组成:
- RedNode 类:表示红点的节点,每个节点可以有子节点和父节点。
- IRedPoint 接口:定义了红点节点的基本行为。
- RedManager 类:管理所有的红点节点,提供节点的注册和管理功能。
RedNode 类
RedNode
类实现了 IRedPoint
接口,包含以下主要成员:
redType
:节点类型(主节点或子节点)。MountObject
:该节点挂载的游戏对象。Children
:子节点列表。UpdateEvents
:节点状态更新事件。hasRedPoint
和cachedHasRedPoint
:当前节点是否有红点及其缓存状态。parent
:父节点引用。
节点的红点状态通过 GetSetHasRedPoint
属性进行管理,该属性会触发红点状态的更新和事件通知。
RedManager 类
RedManager
类负责管理红点节点,包含以下主要功能:
MasterNode
:主节点字典。objectToNodeMap
:游戏对象与红点节点的映射。AddMasterNode
:添加主节点和子节点。ClickToRefreshTheEvent
:处理红点点击事件,刷新红点状态。RegisterNode
:注册红点节点。
public enum RedType
{
MasterNode,
SecondaryNode,
}
public interface IRedPoint
{
bool HasRedPoint();
}
public class RedNode : IRedPoint
{
public RedType redType;
public GameObject MountObject;
public List<RedNode> Children { get; private set; } = new List<RedNode>();
public UnityEngine.Events.UnityAction UpdateEvents;
private bool hasRedPoint;
private bool cachedHasRedPoint;
private RedNode parent;
public bool GetSetHasRedPoint
{
get => hasRedPoint;
set
{
if (Children.Count > 0)
return;
if (hasRedPoint != value)
{
hasRedPoint = value;
OnRedPointChanged();
}
}
}
public bool CachedHasRedPoint
{
get => cachedHasRedPoint;
private set
{
if (cachedHasRedPoint != value)
{
cachedHasRedPoint = value;
UpdateRedPointState();
}
}
}
public RedNode(RedType type, GameObject mountObject)
{
redType = type;
MountObject = mountObject;
}
public void SetRedPoint(bool hasRedPoint)
{
this.hasRedPoint = hasRedPoint;
}
private void OnRedPointChanged()
{
UpdateEvents?.Invoke();
parent?.OnChildRedPointChanged();
UpdateRedPointState();
}
private void OnChildRedPointChanged()
{
UpdateRedPointState();
//UpdateCachedRedPointState();
UpdateEvents?.Invoke();
parent?.OnChildRedPointChanged();
}
private void UpdateRedPointState()
{
if (MountObject != null)
{
Transform Red = MountObject.transform.Find("red");// SendMessage("SetRedPointActive", CachedHasRedPoint);
Text text = MountObject.transform.Find("count").GetComponent<Text>();
Red.gameObject.SetActive(Children.Count > 0);
text.text = Children.Count.ToString();
}
//foreach (var child in Children)
//{
// child.UpdateRedPointState();
//}
}
public void AddChild(RedNode child)
{
if (child != null && !Children.Contains(child))
{
Children.Add(child);
child.parent = this;
child.UpdateRedPointState();
child.parent.UpdateRedPointState();
}
}
public bool HasRedPoint()
{
return CachedHasRedPoint;
}
}
public class RedManager
{
public Dictionary<string, RedNode> MasterNode { get; private set; }
//创建一个缓存池子 便于查找
public Dictionary<GameObject, RedNode> objectToNodeMap { get; private set; }
public RedManager()
{
MasterNode = new Dictionary<string, RedNode>();
}
public void AddMasterNode(GameObject obj,GameObject parentNode)
{
if (objectToNodeMap.ContainsKey(obj)) return;
RedNode ParentNode = objectToNodeMap.ContainsKey(parentNode) ? objectToNodeMap[parentNode]: null;
RedType Redtype = ParentNode==null ? RedType.MasterNode : RedType.SecondaryNode;
RedNode Node = new RedNode(Redtype, obj);
if (ParentNode==null)
MasterNode.Add(obj.name, Node);
else
ParentNode.AddChild(Node);
RegisterNode(Node);
}
public void ClickToRefreshTheEvent(GameObject obj )
{
RedNode ParentNode;
if (!objectToNodeMap.TryGetValue(obj, out ParentNode))
Debug.LogError("Node not registered in the red point system");
else
ParentNode.GetSetHasRedPoint = false;
}
public void RegisterNode(RedNode node)
{
if (!objectToNodeMap.ContainsKey(node.MountObject))
objectToNodeMap.Add(node.MountObject, node);
//for (int i = 0; i < node.Children.Count; i++)
//{
// RegisterNode(node.Children[i]);
//}
}
}