Unity MyFramework 用法说明(七):使用 RedPointSystem 构建树形红点

游戏里的邮件、私聊、成就等功能通常都需要红点提示。MyFramework 使用树形 RedPoint 组织红点状态,子节点变化后会自动向上刷新父节点。

项目地址:

github.com/ZHOURUIH/My...

一、本篇目标

创建下面的红点结构:

bash 复制代码
主菜单红点
├── 邮件红点
├── 私聊红点
└── 成就红点

邮件下面还可以继续挂每一封邮件的红点:

bash 复制代码
邮件红点
├── 邮件1
├── 邮件2
└── 邮件3

叶节点负责判断具体业务状态,父节点只负责汇总子节点:

bash 复制代码
任意一封邮件未读
    ↓
邮件按钮显示红点
    ↓
主菜单按钮显示红点

二、创建项目红点树

创建 RedPointManager

bash 复制代码
using static FrameBaseHotFix;

public class RedPointManager : FrameSystem
{
	public static RedPoint mMain;
	public static RedPoint mMainMail;
	public static RedPoint mMainPrivateChat;
	public static RedPoint mMainAchivement;

	public override void init()
	{
		base.init();

		mRedPointSystem.createRedPoint(out mMain);
		mRedPointSystem.createRedPoint(out mMainMail, mMain);
		mRedPointSystem.createRedPoint(out mMainPrivateChat, mMain);
		mRedPointSystem.createRedPoint(out mMainAchivement, mMain);
	}
}

这里创建的都是普通 RedPoint

普通节点不判断业务数据,只要任意子节点显示,它就会自动显示。

三、注册 RedPointManager

GameHotFix.initFrameSystem() 中注册:

bash 复制代码
protected override void initFrameSystem()
{
	registeFrameSystem<RedPointManager>((com) =>
	{
		mRedPointManager = com;
	});
}

RedPointManager 应尽早创建红点树,确保邮件、私聊等业务数据初始化时能够找到对应父节点。

四、创建邮件叶节点

具体业务红点需要继承 RedPoint

bash 复制代码
public class RedPointMail : RedPoint
{
	protected Mail mMail;

	protected override void initEventType()
	{
		base.initEventType();

		addEvent<EventUnreadMailChanged>();
	}

	public override void resetProperty()
	{
		base.resetProperty();

		mMail = null;
	}

	public void setMail(Mail mail)
	{
		mMail = mail;
	}

	public override void refresh()
	{
		setEnable(!mMail.isRead());
	}
}

这个红点只关心一件事:

bash 复制代码
邮件未读    显示红点
邮件已读    隐藏红点

initEventType() 中注册了 EventUnreadMailChanged。收到事件以后,红点会被标记为需要刷新。

五、给每封邮件创建红点

邮件数据创建时,同时创建对应的红点:

bash 复制代码
using static FrameBaseHotFix;
using static RedPointManager;

public class Mail : ClassObject
{
	protected RedPointMail mRedPoint;
	protected bool mHasRead;

	public void init()
	{
		mRedPointSystem
			.createRedPoint<RedPointMail>(mMainMail)
			.setMail(this);
	}

	public override void destroy()
	{
		mRedPointSystem?.destroyRedPoint(mRedPoint);
		mRedPoint = null;

		base.destroy();
	}

	public void setRead(bool read)
	{
		mHasRead = read;
	}

	public bool isRead()
	{
		return mHasRead;
	}

	public RedPointMail getRedPoint()
	{
		return mRedPoint;
	}
}

为了保存创建出来的红点,代码应写成:

bash 复制代码
public void init()
{
	mRedPointSystem
		.createRedPoint(out mRedPoint, mMainMail)
		.setMail(this);
}

邮件销毁时,红点也要一起销毁。销毁叶节点后,框架会自动重新计算父节点状态。

六、邮件状态变化时发送事件

读取邮件后发送事件:

bash 复制代码
using static FrameBaseHotFix;

public class CmdGlobalReadMail
{
	public static void execute(Mail mail)
	{
		if (mail.isRead())
		{
			return;
		}

		mail.setRead(true);
		mEventSystem.pushEvent<EventUnreadMailChanged>();

		CSMailRead.send(mail.getInstanceID());
	}
}

事件本身不需要携带具体邮件:

bash 复制代码
public class EventUnreadMailChanged : GameEvent
{
}

所有 RedPointMail 收到事件后都会标记为脏状态。RedPointSystem 会在更新时统一刷新,并把变化向父节点传递。

bash 复制代码
EventUnreadMailChanged
    ↓
刷新每封邮件红点
    ↓
刷新邮件入口红点
    ↓
刷新主菜单红点

同一帧内多次触发事件,也只需要统一刷新一次。

七、绑定红点 UI

在 Prefab 中准备红点节点:

bash 复制代码
Mail
└── MailRedPoint

MailRedPoint 可以添加一个 UGUI Image 显示红点图案,生成类型使用:

bash 复制代码
myUGUIObject

界面初始化时绑定:

bash 复制代码
public override void init()
{
	base.init();

	RedPointManager.mMainMail.bindPointUI(mMailRedPoint);
}

界面销毁时取消绑定:

bash 复制代码
public override void destroy()
{
	RedPointManager.mMainMail.removePointUI(mMailRedPoint);

	base.destroy();
}

绑定后不需要手动调用:

bash 复制代码
mMailRedPoint.setActive(...);

红点状态变化时,RedPoint 会自动控制节点的显示和隐藏。

同一个红点数据也可以绑定多个 UI 节点。例如邮件入口同时出现在主界面和功能菜单中,两个位置可以绑定同一个 mMainMail

八、列表项中的红点

每一封邮件的列表项,可以绑定自己的叶节点:

bash 复制代码
public void setMail(Mail mail)
{
	mMail = mail;
	mMail.getRedPoint().bindPointUI(mUnreadMark);
}

列表项回收时必须取消绑定:

bash 复制代码
public override void recycle()
{
	if (mMail.isValid())
	{
		mMail.getRedPoint()?.removePointUI(mUnreadMark);
	}

	mMail = null;
	base.recycle();
}

否则 UI 节点已经被回收或销毁后,红点仍然会尝试更新它。

九、显示未读数量

需要显示数字时,可以继承 RedPointCount

bash 复制代码
public class RedPointPrivateChat : RedPointCount
{
	protected PrivateChatInfo mChat;

	protected override void initEventType()
	{
		base.initEventType();

		addEvent<EventPrivateChange>();
	}

	public void setPrivateChat(PrivateChatInfo chat)
	{
		mChat = chat;
	}

	public override void refresh()
	{
		setCount(mChat.getUnreadCount());
	}
}

绑定红点节点和数量文本:

bash 复制代码
mPrivateChat
	.getRedPoint()
	.setPointUI(mMessagePoint, mUnreadMessageCount);

当数量大于 0 时显示红点,为 0 时自动隐藏。

回收时同样要取消绑定:

bash 复制代码
mPrivateChat
	?.getRedPoint()
	?.removePointUI(mMessagePoint, mUnreadMessageCount);

十、使用规则

使用红点系统时主要注意四件事:

父节点使用普通 RedPoint,叶节点才继承并重写 refresh()

不要在多个界面里分别判断"是否有未读邮件"。业务状态只由 RedPointMail 判断,界面只负责绑定显示节点。

十一、总结

树形红点系统把业务判断和 UI 表现分开:

bash 复制代码
业务数据
    ↓
叶节点判断状态
    ↓
父节点自动汇总
    ↓
所有绑定的 UI 自动刷新

新增一种红点时,只需要:

bash 复制代码
创建 RedPoint 子类
注册关注的事件
实现 refresh()
挂到对应父节点
绑定 UI 节点

这样邮件、私聊、成就等功能可以共用同一套红点更新流程,不需要在每个界面中重复查询业务状态。

相关推荐
SmalBox9 小时前
【节点】[EvaluateScatteringColor节点]原理解析与实际应用
unity3d·游戏开发·图形学
SmalBox1 天前
【节点】[EvaluateRefractionData节点]原理解析与实际应用
unity3d·游戏开发·图形学
_zhourui_h_1 天前
Unity MyFramework 用法说明(六):使用 FrameSystem 管理全局快捷键
unity3d·游戏开发
_zhourui_h_2 天前
Unity MyFramework 用法说明(五):使用 GameScene 和 SceneProcedure 管理业务流程
unity3d·游戏开发
_zhourui_h_2 天前
Unity MyFramework 用法说明(四):使用 UGUIGenerator 自动生成 UI 代码
unity3d
SmalBox3 天前
【节点】[EvaluateFoamData节点]原理解析与实际应用
unity3d·游戏开发·图形学
SmalBox4 天前
【节点】[ComputeVertexPosition节点]原理解析与实际应用
unity3d·游戏开发·图形学
SmalBox5 天前
【节点】[ScleraUVLocation节点]原理解析与实际应用
unity3d·游戏开发·图形学