「Unity博主营地第一期」于2019年11月开启,现已收到数百篇原创投稿。每周根据Unity Connect社区反馈,帮助大家发现最优质、最干货、最受欢迎的博文作品。

在使用Unity开发游戏的时候经常用到红点系统,当玩家点击之后,或者收到服务器数据之后,都需要刷新红点的显示。如果每个人都自己写自己的红点模块,会增加不少的重复任务量,因此迫切需要一个通用的红点系统,其他模块只需要编写自己模块的红点类型和对应的是否显示红点的判断即可。因此RedDotManager应运而生。

案例演示

下面通过一个邮件红点来演示如何操作使用。如下图,当点击系统邮件按钮和玩家邮件按钮之后,对应按钮上面的红点会消除,两个按钮分别点击之后,所有邮件按钮上面的红点才消除。

我们在每个按钮下面都拖上一个带有RedDotItem脚本的红点Prefab。

上图中的“Image”就是红点,我们只要在逻辑层控制该“Image”的显示即可。

图中可以看到该红点可以设置多个红点类型,也就是支持一个红点由多个含义。比如所有邮件按钮上的红点就是由系统邮件和玩家邮件一起控制显示,当任意一个返回true,显示红点的时候,该红点就需要一直显示。直到该RedDotTypes下面的所有逻辑都返回false的时候,红点才不显示。

红点类型--RedDotType

/** * 红点类型的枚举; * RedDotType.cs * * Created by Onelei 12/11/2017 10:28:04 AM. All rights reserved.**/namespace RedDot{ public enum RedDotType { None = 0, Email_UnReadSystem = 1, Email_UnReadPlayer = 2, }}

右滑查看全部代码

红点组件--RedDotItem

我们看下红点身上的组件RedDotItem.cs

/** * 红点物体; * RedDotItem.cs * * Created by Onelei 12/11/2017 10:21:47 AM. All rights reserved.**/using UnityEngine;using UnityEngine.UI;using System.Collections.Generic;namespace RedDot{ public class RedDotItem : MonoBehaviour { /// /// 红点物体; /// public GameObject Go_RedDot; /// /// 红点类型; /// public List redDotTypes; private bool bCachedRedDot = false; void Start() { //注册红点; RedDotManager.Instance.RegisterRedDot(redDotTypes, this); //设置红点; bool bRedDot = RedDotManager.Instance.Check(redDotTypes); SetData(bRedDot, true); } void OnDestroy() { //取消注册红点; RedDotManager.Instance.UnRegisterRedDot(this); } /// /// 设置红点显示; /// /// public void SetData(bool bRedDot, bool bForceRefresh = false) { if (bForceRefresh) { Go_RedDot.SetActive(bRedDot); bCachedRedDot = bRedDot; return; } if (bCachedRedDot != bRedDot) { Go_RedDot.SetActive(bRedDot); bCachedRedDot = bRedDot; } } /// /// 获取当前物体挂载的所有红点; /// /// public List GetRedDotTypes() { return this.redDotTypes; } }}

右滑查看全部代码

在Start和OnDestroy的时候,注册和反注册红点消息的监听。在Start的时候根据自身的红点类型来判断是否显示红点即可。此时红点的GameObject也注册进去了,所以,后面只要根据红点是否显示,直接在管理类里面控制刷新显示即可。

RedDotManager.cs是红点的管理类,该类主要用来将注册进来的红点使用Dictionary统一管理。

红点初始化--Initilize

/// /// 初始化红点系统(注意只需要初始化一次); /// public void Initilize() { RedDotConditionDict.Clear(); // 添加红点数据判断; RedDotConditionDict.Add(RedDotType.Email_UnReadSystem, new RedDot_EmailUnReadSystem()); RedDotConditionDict.Add(RedDotType.Email_UnReadPlayer, new RedDot_EmailUnReadPlayer()); }

右滑查看全部代码

我们需要一个通用的红点判断的基类,因此设计RedDotBase如下:

/** * 红点数据类-基类; * RedDotBase.cs * * Created by Onelei 12/11/2017 10:23:47 AM. All rights reserved.**/namespace RedDot{ public abstract class RedDotBase { /// /// 是否显示红点(true表示显示,false表示不显示;) /// /// /// public virtual bool ShowRedDot(object[] objs) { return false; } }}

右滑查看全部代码

不同的红点判断继承该父类,子类重写ShowRedDot函数即可。我们看下红点判断函数的实现:

/** * 未读邮件红点判断逻辑-玩家红点; * RedDot_EmailUnReadPlayer.cs * * Created by Onelei 12/11/2017 10:25:00 AM. All rights reserved.**/using RedDot;public class RedDot_EmailUnReadPlayer : RedDotBase{ public override bool ShowRedDot(object[] objs) { return MailManager.Instance.IsPlayerRedDot(); }}

/** * 未读邮件红点判断逻辑-系统红点; * RedDot_EmailUnRead.cs * * Created by Onelei 12/11/2017 10:25:00 AM. All rights reserved.**/using RedDot;public class RedDot_EmailUnReadSystem : RedDotBase{ public override bool ShowRedDot(object[] objs) { return MailManager.Instance.IsSystemRedDot(); }}

右滑查看全部代码

我们通过MailManager里面的数据类判断是否显示红点,ShowRedDot函数的参数是object数组,方便检查红点的时候传入参数。比如判断某个英雄是否可以升级,就可以传入英雄的ID。

红点注册--RegisterRedDot

   

/// /// 添加红点界面; /// /// /// private void RegisterRedDot(RedDotType redDotType, RedDotItem item) { if (RedDotObjDict.ContainsKey(redDotType)) { RedDotObjDict[redDotType].Add(item); } else { List items = new List(); items.Add(item); RedDotObjDict.Add(redDotType, items); } }

右滑查看全部代码

红点检查--Check是否显示

/// /// 检查红点提示,内部调用; /// /// /// private bool Check(RedDotType redDotType, object[] objs) { if (RedDotConditionDict.ContainsKey(redDotType)) { return RedDotConditionDict[redDotType].ShowRedDot(objs); } return false; }

右滑查看全部代码

红点系统管理类--RedDotManager

完整代码如下:

/** * 红点系统管理类; * RedDotManager.cs * * Created by Onelei 12/11/2017 10:21:47 AM. All rights reserved.**/using System.Collections.Generic;namespace RedDot{ public class RedDotManager { private static RedDotManager _instance; public static RedDotManager Instance { get { if (null == _instance) { _instance = new RedDotManager(); } return _instance; } } /// /// 红点数据; /// Dictionary RedDotConditionDict = new Dictionary(); /// /// 红点物体; /// Dictionary> RedDotObjDict = new Dictionary>(); /// /// 初始化红点系统(注意只需要初始化一次); /// public void Initilize() { RedDotConditionDict.Clear(); // 添加红点数据判断; RedDotConditionDict.Add(RedDotType.Email_UnReadSystem, new RedDot_EmailUnReadSystem()); RedDotConditionDict.Add(RedDotType.Email_UnReadPlayer, new RedDot_EmailUnReadPlayer()); } /// /// 注册红点; /// /// /// public void RegisterRedDot(List redDotTypes, RedDotItem item) { for (int i = 0; i < redDotTypes.Count; i++) { RegisterRedDot(redDotTypes[i], item); } } /// /// 取消注册红点; /// /// public void UnRegisterRedDot(RedDotItem item) { Dictionary>.Enumerator itor = RedDotObjDict.GetEnumerator(); while (itor.MoveNext()) { List redDotItems = itor.Current.Value; if (redDotItems.Contains(item)) { redDotItems.Remove(item); break; } } } /// /// 检查红点提示; /// /// /// public bool Check(List redDotTypes, object[] objs = null) { for (int i = 0; i < redDotTypes.Count; i++) { //只要有一个需要点亮,就显示; if (Check(redDotTypes[i], objs)) { return true; } } return false; } /// /// 更新该类型的所有红点组件; /// /// /// public void NotifyAll(RedDotType redDotType, object[] objs = null) { if (RedDotObjDict.ContainsKey(redDotType)) { for (int i = 0; i < RedDotObjDict[redDotType].Count; i++) { RedDotItem item = RedDotObjDict[redDotType][i]; if (item != null) { List redDotTypes = item.GetRedDotTypes(); bool bCheck = Check(redDotTypes, objs); item.SetData(bCheck); } } } } #region private /// /// 添加红点界面; /// /// /// private void RegisterRedDot(RedDotType redDotType, RedDotItem item) { if (RedDotObjDict.ContainsKey(redDotType)) { RedDotObjDict[redDotType].Add(item); } else { List items = new List(); items.Add(item); RedDotObjDict.Add(redDotType, items); } } /// /// 检查红点提示,内部调用; /// /// /// private bool Check(RedDotType redDotType, object[] objs) { if (RedDotConditionDict.ContainsKey(redDotType)) { return RedDotConditionDict[redDotType].ShowRedDot(objs); } return false; } #endregion }}

测试

编写一个测试函数,在Start函数里面添加按钮的回调。

// Use this for initialization void Start() { // 设置按钮回调; Button_EmailSystem.onClick.AddListener(OnClickEmailSystem); Button_EmailPlayer.onClick.AddListener(OnClickEmailPlayer); }

右滑查看全部代码

我们需要在按钮点击的时候,计算该红点类型所对应的的红点逻辑,同时刷新所有绑定了该红点类型的RedDotItem身上的红点。

/// /// 系统按钮的回调;/// void OnClickEmailSystem() {// 点击之后表示邮件读取过了,设置邮件为已读状态;// (注意这里不能够设置红点的显隐,因为是有数据控制的,所以要控制数据那边的红点逻辑);// RedDot.RedDotManager.Instance.SetData(RedDot.RedDotType.Email_UnRead,false); RedDot.MailManager.Instance.SetSystemRedDot(false); RedDot.RedDotManager.Instance.NotifyAll(RedDot.RedDotType.Email_UnReadSystem); }/// /// 玩家按钮的回调;/// void OnClickEmailPlayer() {// 点击之后表示邮件读取过了,设置邮件为已读状态;// (注意这里不能够设置红点的显隐,因为是有数据控制的,所以要控制数据那边的红点逻辑);// RedDot.RedDotManager.Instance.SetData(RedDot.RedDotType.Email_UnRead,false); RedDot.MailManager.Instance.SetPlayerRedDot(false); RedDot.RedDotManager.Instance.NotifyAll(RedDot.RedDotType.Email_UnReadPlayer); }

右滑查看全部代码

总结

我们将红点的数据和表现分离,通过RedDotItem来控制红点的显示。RedDotItem是一个单独的Prefab,我们可以设计不同的红点,比如红点上面是否有数字等,都可以在一个RedDotItem上面进行扩展。同时还支持一个红点类型绑定在不同的Prefab上面,一个Prefab上面绑定多个红点。这样一对多的关系,我们使用Dictionary来方便管理,Key就是红点类型,Value是一个List,里面包含了该类型绑定的所有RedDotItem。只要取出来对应的红点类型的红点是否和之前不一样,不一样就刷新该Key对应的Value的所有RedDotItem红点的显示即可。

关注博主

unity.cn/u/onelei-vy

明日,我们将停更一日,各位节日安康。

django权限系统实现步骤_博主营地 | Unity红点系统如何实现?超全步骤分享相关推荐

  1. [安卓刷机实战]小米/红米手机刷机降系统图文教程-解锁小米手机-K30 5G版[开箱可用][解锁+刷机全步骤教程]

    [安卓刷机实战]小米/红米手机刷机降系统图文教程-解锁小米手机-K30 5G版[开箱可用][解锁+刷机全步骤教程] 1.准备需要的软件 2.安装软件/驱动 2.1安装小米手机助手 2.2安装MiFla ...

  2. 惠普电脑u盘重装系统步骤_惠普台式机u盘重装系统win10详细步骤及注意事项

    [文章导读]最近有很多网友问惠普台预装的win10系统不好用想重装,但是由于惠普台式机采用UEFI模式,不能像普通方式那样安装,需要用u盘的方式安装,并且BIOS要相关设置以及硬盘模式要对应,那么惠普 ...

  3. 惠普电脑u盘重装系统步骤_惠普笔记本电脑U盘重装win10系统的详细方法教程

    惠普电脑质量可靠,服务优异,不少朋友在选择电脑时会购买惠普笔记本,如果使用过程中遇到无法开机的问题时,怎么办呢?此时最直接的方法就是U盘重装了,下面小编介绍惠普笔记本电脑U盘重装win10系统的详细方 ...

  4. 苹果手机mov文件如何复制到电脑_如何在手机上访问电脑上的文件(超详细步骤) iPhone版...

    之前分享了如何在两台电脑上共享文件,如需访问可点击如下链接: Town-Tree:如何在两台电脑之间共享文件(超详细步骤)​zhuanlan.zhihu.com 如何在安卓手机上访问电脑上的文件,可点 ...

  5. c语言编写订货系统,学位论文_基于c语言的仓库订货系统的仿真.doc

    学位论文_基于c语言的仓库订货系统的仿真 本科毕业论文(设计.创作) 题目: 基于C语言的仓库订货系统的仿真 学生姓名: 学号: 所在系院: 信息与通信技术系 专业: 电子信息工程 入学时间: 201 ...

  6. python车牌识别系统抬杆_昆明车牌识别自动抬杆系统

    您当前的位置:首页 » 供应产品 » 昆明车牌识别自动抬杆系统 昆明车牌识别自动抬杆系统 点击图片查看大图 产品/服务: 浏览次数:679车牌识别自动抬杆系统 规 格: 标准 品 牌: 交安通 单 价 ...

  7. 系统对接方案_报销费控SaaS对接财务系统解决方案

    方案简介 报销费控SaaS对接财务系统解决方案,为SaaS服务商提供一站式适配和对接多种财务.ERP系统的服务,帮助SaaS服务商为企业用户提供财务科目配置.一键生成凭证和后续功能升级等服务. Saa ...

  8. 道路监控系统java代码_使用Java实现简单的监控系统

    本文只是简单介绍了下监控系统实现的思路,具体还需根据自己需求实现. 前言: 目前存在一个后台服务系统,此时需要配套一个监控系统,对这个后台服务系统进行监控.下面会涉及到两个系统,后台服务系统(这是已经 ...

  9. wincc上位机与1200组态步骤_博途v13的wincc能组态上位机吗

    请问博途v13的wincc与wincc v7.3的区别在哪儿 最佳答案 可以的 博图WINCC分三个版本,其中Professional版本可以组态上位机运行系统comfort和basic 版本仅用于触 ...

最新文章

  1. 自己理解接口回调入门
  2. JS高级程序设计拾遗
  3. Linux命令篇之usermod命令和passwd命令
  4. 故障申报系统php源码,运维不再专业救火 不会PHP照样找出代码性能问题
  5. PHP中include、include_once、require、require_once四者区别
  6. js的字符串和变量拼接
  7. 20 WBS要素xxxxxx有不同的存货估价
  8. 基础知识(十)C++常用函数.txt
  9. jsp和mysql乱码
  10. OpenCVQt学习之一——打开图片文件并显示
  11. 【黄金分割点】与【斐波那契数列】
  12. 平安银行支付接口 PHP ECSHOP
  13. SVNAdmin - 好用的开源SVN管理系统
  14. 计算机教室布线施工方案,最新计算机教室施工方案.docx
  15. linux dstat rpm,dstat监控工具介绍
  16. AcWing1402. 星空之夜
  17. 用Python分析《都挺好》中的人物关系
  18. Java练习——小游戏 模拟雷电
  19. QT中主线程终止子线程中的死循环
  20. 一篇文章带你更深入了解区块链有哪些应用?

热门文章

  1. android支付宝余额怎么做,android实现类似于支付宝余额快速闪动的效果 -电脑资料...
  2. php echo nbsp,关于include里面的函数echo的问题
  3. oracle archivelog满了,Oracle archivelog占用100%如何处理?
  4. delphi switch语句例子_「GCTT 出品」Go 系列教程——10. switch 语句
  5. python中if的输入格式_Python基础之输出格式和If判断
  6. 平安夜、圣诞节设计素材和灵感|撒糖(PNG免扣素材)
  7. 网站模型|可以帮助你以一种美丽、独特的方式展示你的网站设计。
  8. 年终庆典高端海报设计PSD分层模板
  9. android @style/name,android style和attr的用法
  10. java volatitl_Java中的关键字volatitle