Unity架构师进阶:红点系统的架构与设计

面试的时候经常被问道如何来设计一个红点系统,本文将详细地介绍如何设计一个红点系统,有哪些接口,并完整地给出实现。

红点系统的需求分析

首先我们来分析一下红点系统的设计需求: 红点系统严格意义上来说不属于框架,而是游戏逻辑,所以代码不要放到通用的框架里面,并不属于基础服务。它是为了在游戏逻辑开发中很好的提示未处理的信息。对于使用者而言,它们希望红点系统能直接给他们提供接口和服务,能方便的把红点显示在特定的节点下,并设置到特定的位置。使用者不用关心红点的"样子",不用关心红点如何创建,反复创建和销毁红点的性能等。

从需求分析得出"红点系统"对外提供的接口如下:

  1. 编写接口"CreateRedPoint",用来创建一个"红点"的节点,返回节点给使用者,至于红点放什么位置由使用者决定;
  2. 编写接口"DestroyRedPoint",用来删除销毁一个红点节点;
  3. 编写接口"SetRedPointValue", 把红点节点传递进来,然后设置红点里面的具体数值;
  4. 编写接口"DestroyAllRedPoints", 用来在UI界面销毁时把它下面所有的红点都删除回收;

由于"红点系统"会要经常创建和删除节点,所以内部采用节点池的模式,这样能最大限度地提升性能。

红点系统依赖的基础服务

红点系统并不是完全独立地,依赖框架地基础服务,一个是资源管理,主要负责加载红点的节点资源,一个是节点池管理模块。资源管理模块示例代码里面采用的是YooAssets,然后把红点节点做成预制体,然后通过YooAssets收集打包,然后通过代码来加载节点资源。红点系统内部基于节点池机制,所以要给红点节点创建一个特有的节点池。

  • YooAssets的版本:1.5.2
  • 资源管理ResMgr: 基于YooAssets,做的同步/异步资源管理
  • 节点池: 自己实现,详情见代码;
  • 红点的节点预制体: RedPoint节点下面有两个子节点,一个红色的圆形精灵,一个是文字Label,用来显示数字,如下图所示:   

红点系统代码具体实现

编写一个RedPointFlag组件,继承Component,用来标记哪些节点是红点,这个组件的作用是在一个UI界面销毁的时候,方便利用这个Flag组件,找到所有的"红点",并把它们一起回收。

复制代码
public class RedPointFlag : Component
{
}

编写一个RedPointMgr的全局单例,用来提供"红点"服务。提供Init接口,在Init的时候,给红点的创建一个节点池。代码如下:

复制代码
public class RedPointMgr : UnitySingleton<RedPointMgr>
{
    public void Init() {
        NodePoolMgr.Instance.AddNodePool("GUI/Prefabs/RedPoint.prefab", 10);
}
}

CreateRedPoint接口:

复制代码
public GameObject CreateRedPoint() {
    GameObject redPoint = NodePoolMgr.Instance.Get("GUI/Prefabs/RedPoint.prefab");
    if (redPoint.GetComponent<RedPointFlag>() == null) {
        redPoint.AddComponent<RedPointFlag>();
    }
    return redPoint;
}

在这个接口中要特别的注意,我们给红点节点添加一个RedPointFlag的组件实例,方便后面把所有的红点找出来。

SetRedPointValue接口:

复制代码
public void SetRedPointValue(GameObject redPoint, int value) {
    var label = redPoint.GetComponentInChildren<Text>();
    label.text = value.ToString();
}

用来给红点设置对应的显示值,原理比较简单,找到红点里面的Text组件,修改Text组件的显示内容即可。

DestroyRedPoint接口:

复制代码
public void DestroyRedPoint(GameObject redPoint) {
    NodePoolMgr.Instance.Recycle("GUI/Prefabs/RedPoint.prefab", redPoint);
}

删除一个红点,这里主要是调用节点池回收。

DestroyAllRedPoint接口:

复制代码
public void DestroyAllRedPoint(GameObject uiRoot) {
    RedPointFlag[] redPoints = uiRoot.GetComponentsInChildren<RedPointFlag>();
    for (int i = 0; i < redPoints.Length; i++) {
        NodePoolMgr.Instance.Recycle("GUI/Prefabs/RedPoint.prefab", redPoints[i].gameObject);
    }
}

删除所有的红点,这里就利用了RedPointFlag组件,通过把带有这个组件的所有节点筛选出来,就是我们的红点节点了。然后把所有的节点回收即可。

接下来给个简单的使用示例,用起来非常简单方便,在UI代码里面创建一个红点,并在界面销毁的时候,删除所有的红点:

复制代码
public class UIHomeCtrl : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Transform root = this.transform.Find("Bottom/start/btnStart");

        var redPoint = RedPointMgr.Instance.CreateRedPoint();
        redPoint.transform.SetParent(root, false);
        redPoint.transform.localPosition = new Vector3(120, 40, 0);

        RedPointMgr.Instance.SetRedPointValue(redPoint, 20);
    }

    private void OnDestroy()
    {
        RedPointMgr.Instance.DestroyAllRedPoint(this.gameObject);
    }
}

今天的分享就到这里了,需要完整代码的,可以关注我们 + 企.鹅.裙 428 540 563 获取更多的相关资料。

相关推荐
迎風吹頭髮19 小时前
Linux内核架构浅谈8-Linux内核与UNIX的传承:设计思想与特性差异
linux·运维·架构
sorryhc1 天前
如何设计一个架构良好的前端请求库?
前端·javascript·架构
爱吃小胖橘1 天前
Unity网络开发--超文本传输协议Http(1)
开发语言·网络·网络协议·http·c#·游戏引擎
supermapsupport1 天前
SuperMap iClient3D for WebGL 调用GPA服务实现地质体模型裁剪封边
3d·webgl
SandySY1 天前
品三国谈人性
算法·架构
BrightMZM1 天前
记录一下Unity的BUG,Trial Version
unity·bug·打包·trial
f30517091 天前
Python中的Web框架比较Django、Flask与FastAPI的优缺点分析
游戏
韩非1 天前
if 语句对程序性能的影响
算法·架构
自由的疯1 天前
java DWG文件转图片
java·后端·架构
IT小番茄1 天前
Kubernetes云平台管理实战:服务发现和负载均衡(五)
架构