您的位置:首页 > 产品设计 > UI/UE

游戏UI框架设计(四) : 模态窗体管理

2017-06-23 19:55 555 查看
我们在开发UI窗体时,对于“弹出窗体”往往因为需要玩家优先处理弹出小窗体,则要求玩家不能(无法)点击“父窗体”,这种窗体就是典型的“模态窗体”。在此笔者设计了四种模式类型:完全透明、半透明、低透明度、透明且可以穿透。





(透明不能穿透)






  (半透明不能穿透)







     (低透明度,不能穿透)

     对于“模态窗体”的基本实现原理是:

    在弹出窗体的后面增加一层“UI遮罩窗体”,当需要弹出特定模态窗体时,脚本自动控制“UI遮罩窗体”的“层级”,把弹出模特窗体与普通窗体之间进行隔离,起到突出显示与遮挡用户点击其他窗体的作用。原理如下图所示:





    在上图左边的层级视图中,有一个“_UIMaskPanel”的特殊窗体,这就是“UI遮罩窗体”,在不需要弹出显示的时候,这个窗体是“禁用”状态。 为了更好适用不同开发需求,对于弹出窗体,我们上面定义了关于弹出窗体的不同性质: 完全透明、半透明、低透明度、透明且可以穿透。 这四种类型功能的实现原理是控制“_UIMaskPanel”的颜色数值以及透明度实现的,见下图所示:









说明: 上图右边属性就是“UI遮罩窗体”的属性栏,笔者通过脚本控制Image组件的Color 组件,来实现"模态窗体”的不同显示性质。

   原理讲完,贴出控制代码如下:

/***

 * 

 *    Title: "SUIFW" UI框架项目

 *           主题: UI遮罩管理器  

 *    Description: 

 *           功能: 负责“弹出窗体”模态显示实现

 *                  

 *    Date: 2017

 *    Version: 0.1版本

 *    Modify Recoder: 

 *    

 *   

 */

using System.Collections;

using System.Collections.Generic;

using System.Net.Mime;

using UnityEngine;

using UnityEngine.UI;

namespace SUIFW

{

    public class UIMaskMgr : MonoBehaviour {

        /*  字段 */

        //本脚本私有单例

        private static UIMaskMgr _Instance = null;  

        //UI根节点对象

        private GameObject _GoCanvasRoot = null;

        //UI脚本节点对象

        private Transform _TraUIScriptsNode = null;

        //顶层面板

        private GameObject _GoTopPanel;

        //遮罩面板

        private GameObject _GoMaskPanel;

        //UI摄像机

        private Camera _UICamera;

        //UI摄像机原始的“层深”

        private float _OriginalUICameralDepth;

        //得到实例

        public static UIMaskMgr GetInstance()

        {

            if (_Instance==null)

            {

                _Instance = new GameObject("_UIMaskMgr").AddComponent<UIMaskMgr>();

            }

            return _Instance;

        }

        void Awake()

        {

            //得到UI根节点对象、脚本节点对象

            _GoCanvasRoot = GameObject.FindGameObjectWithTag(SysDefine.SYS_TAG_CANVAS);

            _TraUIScriptsNode = UnityHelper.FindTheChildNode(_GoCanvasRoot, SysDefine.SYS_SCRIPTMANAGER_NODE);

            //把本脚本实例,作为“脚本节点对象”的子节点。

            UnityHelper.AddChildNodeToParentNode(_TraUIScriptsNode,this.gameObject.transform);

            //得到“顶层面板”、“遮罩面板”

            _GoTopPanel = _GoCanvasRoot;

            _GoMaskPanel = UnityHelper.FindTheChildNode(_GoCanvasRoot, "_UIMaskPanel").gameObject;

            //得到UI摄像机原始的“层深”

            _UICamera = GameObject.FindGameObjectWithTag("_TagUICamera").GetComponent<Camera>();

            if (_UICamera != null)

            {

                //得到UI摄像机原始“层深”

                _OriginalUICameralDepth = _UICamera.depth;

            }

            else

            {

                Debug.Log(GetType()+"/Start()/UI_Camera is Null!,Please Check! ");

            }

        }

        /// <summary>

        /// 设置遮罩状态

        /// </summary>

        /// <param name="goDisplayUIForms">需要显示的UI窗体</param>

        /// <param name="lucenyType">显示透明度属性</param>

        public void SetMaskWindow(GameObject goDisplayUIForms,UIFormLucenyType lucenyType=UIFormLucenyType.Lucency)

        {

            //顶层窗体下移

            _GoTopPanel.transform.SetAsLastSibling();

            //启用遮罩窗体以及设置透明度

            switch (lucenyType)

            {

                    //完全透明,不能穿透

                case UIFormLucenyType.Lucency:

                    print("完全透明");

                    _GoMaskPanel.SetActive(true);

                    Color newColor1=new Color(255/255F,255/255F,255/255F,0F/255F);

                    _GoMaskPanel.GetComponent<Image>().color = newColor1; 

                    break;

                    //半透明,不能穿透

                case UIFormLucenyType.Translucence:

                    print("半透明");

                    _GoMaskPanel.SetActive(true);

                    Color newColor2 = new Color(220/255F, 220/255F, 220/255F, 50/255F);

                    _GoMaskPanel.GetComponent<Image>().color = newColor2; 

                    break;

                    //低透明,不能穿透

                case UIFormLucenyType.ImPenetrable:

                    print("低透明");

                    _GoMaskPanel.SetActive(true);

                    Color newColor3=new Color(50/255F,50/255F,50/255F,200F/255F);

                    _GoMaskPanel.GetComponent<Image>().color = newColor3; 

                    break;

                    //可以穿透

                case UIFormLucenyType.Pentrate:

                    print("允许穿透");

                    if (_GoMaskPanel.activeInHierarchy)

                    {

                        _GoMaskPanel.SetActive(false);

                    }

                    break;

                default:

                    break;

            }

            //遮罩窗体下移

            _GoMaskPanel.transform.SetAsLastSibling();

            //显示窗体的下移

            goDisplayUIForms.transform.SetAsLastSibling();

            //增加当前UI摄像机的层深(保证当前摄像机为最前显示)

            if (_UICamera!=null)

            {

                _UICamera.depth = _UICamera.depth + 100;    //增加层深

            }

        }

        /// <summary>

        /// 取消遮罩状态

        /// </summary>

        public void CancelMaskWindow()

        {

            //顶层窗体上移

            _GoTopPanel.transform.SetAsFirstSibling();

            //禁用遮罩窗体

            if (_GoMaskPanel.activeInHierarchy)

            {

                //隐藏

                _GoMaskPanel.SetActive(false);

            }

            //恢复当前UI摄像机的层深 

            if (_UICamera != null)

            {

                _UICamera.depth = _OriginalUICameralDepth;  //恢复层深

            }

        }

    }

}

     关于上述定义的UIMaskMgr.cs 脚本代码 ,笔者在“BaseUIForm.cs” 中做了封装,使其可以在框架中自动管理,无需框架外客户程序的处理。BaseUIForm.cs 代码如下:

/***

 * 

 *    Title: "SUIFW" UI框架项目

 *           主题: UI窗体的父类

 *    Description: 

 *           功能:定义所有UI窗体的父类。

 *           定义四个生命周期

 *           

 *           1:Display 显示状态。

 *           2:Hiding 隐藏状态

 *           3:ReDisplay 再显示状态。

 *           4:Freeze 冻结状态。

 *           

 *                  

 *    Date: 2017

 *    Version: 0.1版本

 *    Modify Recoder: 

 *    

 *   

 */

using System.Collections;

using System.Collections.Generic;

using System.ComponentModel.Design;

using UnityEngine;

namespace SUIFW

{

    public class BaseUIForm : MonoBehaviour {

        /*字段*/

        private UIType _CurrentUIType=new UIType();

        /* 属性*/

        //当前UI窗体类型

        public UIType CurrentUIType

        {

            get { return _CurrentUIType; }

            set { _CurrentUIType = value; }

        }

        #region  窗体的四种(生命周期)状态

        /// <summary>

        /// 显示状态

        /// </summary>

        public virtual void Display()

        {

            this.gameObject.SetActive(true);

            //设置模态窗体调用(必须是弹出窗体)

            if (_CurrentUIType.UIForms_Type==UIFormType.PopUp)

            {

                UIMaskMgr.GetInstance().SetMaskWindow(this.gameObject,_CurrentUIType.UIForm_LucencyType);

            }

        }

        /// <summary>

        /// 隐藏状态

        /// </summary>

        public virtual void Hiding()

        {

            this.gameObject.SetActive(false);

            //取消模态窗体调用

            if (_CurrentUIType.UIForms_Type == UIFormType.PopUp)

            {

                UIMaskMgr.GetInstance().CancelMaskWindow();

            }

        }

        /// <summary>

        /// 重新显示状态

        /// </summary>

        public virtual void Redisplay()

        {

            this.gameObject.SetActive(true);

            //设置模态窗体调用(必须是弹出窗体)

            if (_CurrentUIType.UIForms_Type == UIFormType.PopUp)

            {

                UIMaskMgr.GetInstance().SetMaskWindow(this.gameObject, _CurrentUIType.UIForm_LucencyType);

            }

        }

        /// <summary>

        /// 冻结状态

        /// </summary>

        public virtual void Freeze()

        {

            this.gameObject.SetActive(true);

        }

        #endregion

    }

}

       以上所讲解的是大体实现思路,还有很多的小细节由于时间关系没有披露,所以特提供下载链接,供感兴趣的开发者研究讨论。欢迎大家提供进一步完善的思路与建议。

 

       本游戏UI框架(截止到以上部分)下载参考链接: 链接:http://pan.baidu.com/s/1nv4plFV 密码:6o0n

       说明: 如果有想进一步查看笔者更加详细的视频讲解,请围观以下地址:

       链接: http://edu.51cto.com/course/course_id-8411.html
先讲解到这,我们下次讲解: 游戏UI框架设计(五):配置管理与日志系统

本文出自 “刘老师讲Unity” 博客,请务必保留此出处http://liuguozhu.blog.51cto.com/9142031/1904187
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: