Unity3D 通用提示窗口实现分析(Inventory Pro学习总结) |
您所在的位置:网站首页 › unity弹出窗口 › Unity3D 通用提示窗口实现分析(Inventory Pro学习总结) |
加载电子文档,耐心等待,看不清可试试全屏
中间小电脑代表全屏, 左右箭头代码自适应宽
背景
游戏中的UI系统或者叫做GUI窗口系统主要有:主要装备窗口(背包,角色窗口也是一种特殊窗口)、确实提示窗口(如购买确认)、信息提示窗口(一 遍没有按钮,ContexntMenu)和特殊窗口(聊天记录或者技能树),前篇已经介绍分析了Inventory Pro确认提示窗口的设计和实现方式,这篇主要讲一下信息提示窗口的实现。本以为提示窗口是比较简单的,毕竟没有按钮事件交互的问题,但是分析了下源代码 还是让我有些惊讶,插件作者在提示窗口中考虑到了性能问题,由于本人一直在PC端开发程序没有移动端的经验,所以在移动端对于性能优化还是比较关注的。 插件效果及使用左下角即为信息提示窗口NoticeUI,当信息提示比较多时,具有滚动条和超出自动隐藏的功能,是通过对象池技术实现,提高性能和效率 通过拖拽的方式创建好UI界面,红框中我们看到了组件树的结构和类型 在NoticeUI上绑定NoticeUI脚本,设置好每一行显示的预设NoticeMessageUI,ScrollRect等相关属性,基本就已经完成了关于信息提示窗口的实现了 源代码分析老规矩上类图 类图分析经过这段时间的学习,我真的慢慢爱上了VS的类图分析了,希望新手同学也能习惯这点。VS的类图很强大能自动生成关联关系和继承接口等信息,是特别舒心的类图工具。 A、先看下Message模型(Model)类,InventoryNoticeMessage继承了InventoryMessage,继承后拥 有的字段有,消息,标题,颜色,消失延时,时间看到这些字段我们大致也可以猜到信息提示窗口有哪些功能了吧(其实是可以扩展的),这里需要重点关注下 Show方法(后面源码分析再表述) B、NoticeUI和NoticeMessageUI都是MonoBehavior的子类,也就是说他们都是组件,分析其字段有具有 ScrollRect和Text说明他们都是需要和UI进行绑定的。这里特变关注下VS使用双箭头表示组合关联,所以NoticeUI组合关联 NoticeMessageUI,而继承了IPoolableObject接口顾名思义它具有入对象池的能力,也就是可以加入对象池,我们也看到了 NoticeUI有一个InventoryPool,我们大概可以猜到NoticeUI中 List和InevntoryPool猥琐的关系。 调用流程分析调用的流程其实可以画一个流程图,这里只是简单的描述一下 1、InventoryNoticeMessage.Show() –>2、 全局NoticeUI.AddMessage()->3、InventoryPool池对象 NoticeMessageUI.SetMessage()->4、NoticMessageUI通过setAictive(true)进行显示 ->5、NoticeUI.Update,通过循环调用NoticMessageUI的showTime.deltaTime做控制隐藏 1、InventoryNoticeMessage.Show() 通过以上代码我们看的出来其实notice也是一个全局的UI,所以才可以通过单例来访问,应该是有固定区域的。 2、 全局NoticeUI.AddMessage() NoticeUI中的AddMessage就比较复杂了,主要要处理几个事情A、事件触发;B、滚动处理;C、对象池获取 NoticeMessageUI并激活显示D、List和 InventoryPool好基友的处理(对象池的回收及引用数组的移除) 3、InventoryPool池对象NoticeMessageUI.SetMessage() SetMessage() 就像它的方法名一样好像什么也没有做的样子,只是设置了一些简单字段的内容以及显示时间,实际的显示激活却是在4对象池获取的时候置位的。 4、NoticMessageUI通过setAictive(true)进行显示 对象池的使用和回收是通过池对象的activeSelf属性来确定的,这个开关有一箭双雕的意思,既通过它来控制对象池的使用和回收,又用于控制UI对象的演示与否。 5、NoticeUI.Update,通过循环调用NoticMessageUI的showTime.deltaTime控制隐藏 通过显示时间来控制信息的隐藏 隐藏函数使用了动画效果,由于动画是有显示时间的,所以通过一个字段isHiding做为状态判断。 核心源码NoticeUI 复制内容到剪贴板 using UnityEngine; using UnityEngine.EventSystems; using System; using System.Collections; using System.Collections.Generic; using Devdog.InventorySystem.Models; using Devdog.InventorySystem.UI.Models; using UnityEngine.UI; namespace Devdog.InventorySystem { /// /// How long a message should last. /// Parse to int to get time in seconds. /// public enum NoticeDuration { Short = 2, Medium = 4, Long = 6, ExtraLong = 8 } [AddComponentMenu("InventorySystem/Windows/Notice")] public partial class NoticeUI : MonoBehaviour { #region Events /// /// Note that it also fired when message == null or empty, even though the system won't process the message. /// This is because someone might want to implement their own system and just use the event as a link to connect the 2 systems. /// /// /// /// /// public delegate void NewMessage(InventoryNoticeMessage message, params System.Object[] parameters); public event NewMessage OnNewMessage; #endregion [Header("General")] public NoticeMessageUI noticeRowPrefab; [InventoryRequired] public RectTransform container; public ScrollRect scrollRect; public AudioClip onNewMessageAudioClip; /// /// When more messages come in the last items will be removed. /// [Header("Messages")] public int maxMessages = 50; /// /// Remove the item after the show time has passed, if false, the item will continue to exist. /// public bool destroyAfterShowTime = true; /// /// All show times are multiplied by this value, if you want to increase all times, use this value. /// public float showTimeFactor = 1.0f; [NonSerialized] protected List messages = new List(8); private InventoryPool pool; public virtual void Awake() { pool = new InventoryPool(noticeRowPrefab, maxMessages); } public virtual void Update() { if (destroyAfterShowTime == false) return; foreach (var message in messages) { message.showTime -= Time.deltaTime; if (message.showTime |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |