游戲UI框架設計(四) : 模態窗體管理


游戲UI框架設計(四)

--模態窗體管理

 

  我們在開發UI窗體時,對於“彈出窗體”往往因為需要玩家優先處理彈出小窗體,則要求玩家不能(無法)點擊“父窗體”,這種窗體就是典型的“模態窗體”。在此筆者設計了四種模式類型:完全透明、半透明、低透明度、透明且可以穿透。

    

  (透明不能穿透)

    

    (半透明不能穿透)

    

     (低透明度,不能穿透)

     對於“模態窗體”的基本實現原理是:

    在彈出窗體的后面增加一層“UI遮罩窗體”,當需要彈出特定模態窗體時,腳本自動控制“UI遮罩窗體”的“層級”,把彈出模特窗體與普通窗體之間進行隔離,起到突出顯示與遮擋用戶點擊其他窗體的作用。原理如下圖所示:

   

    在上圖左邊的層級視圖中,有一個“_UIMaskPanel”的特殊窗體,這就是“UI遮罩窗體”,在不需要彈出顯示的時候,這個窗體是“禁用”狀態。 為了更好適用不同開發需求,對於彈出窗體,我們上面定義了關於彈出窗體的不同性質: 完全透明、半透明、低透明度、透明且可以穿透。 這四種類型功能的實現原理是控制“_UIMaskPanel”的顏色數值以及透明度實現的,見下圖所示:

  

   說明: 上圖右邊屬性就是“UI遮罩窗體”的屬性欄,筆者通過腳本控制Image組件的Color 組件,來實現"模態窗體”的不同顯示性質。

   原理講完,貼出控制代碼如下:

 

  1 /***
  2  * 
  3  *    Title: "SUIFW" UI框架項目
  4  *           主題: UI遮罩管理器  
  5  *    Description: 
  6  *           功能: 負責“彈出窗體”模態顯示實現
  7  *                  
  8  *    Date: 2017
  9  *    Version: 0.1版本
 10  *    Modify Recoder: 
 11  *    
 12  *   
 13  */
 14 using System.Collections;
 15 using System.Collections.Generic;
 16 using System.Net.Mime;
 17 using UnityEngine;
 18 using UnityEngine.UI;
 19 
 20 namespace SUIFW
 21 {
 22     public class UIMaskMgr : MonoBehaviour {
 23         /*  字段 */
 24         //本腳本私有單例
 25         private static UIMaskMgr _Instance = null;  
 26         //UI根節點對象
 27         private GameObject _GoCanvasRoot = null;
 28         //UI腳本節點對象
 29         private Transform _TraUIScriptsNode = null;
 30         //頂層面板
 31         private GameObject _GoTopPanel;
 32         //遮罩面板
 33         private GameObject _GoMaskPanel;
 34         //UI攝像機
 35         private Camera _UICamera;
 36         //UI攝像機原始的“層深”
 37         private float _OriginalUICameralDepth;
 38 
 39         //得到實例
 40         public static UIMaskMgr GetInstance()
 41         {
 42             if (_Instance==null)
 43             {
 44                 _Instance = new GameObject("_UIMaskMgr").AddComponent<UIMaskMgr>();
 45             }
 46             return _Instance;
 47         }
 48 
 49 
 50 
 51 
 52         void Awake()
 53         {
 54             //得到UI根節點對象、腳本節點對象
 55             _GoCanvasRoot = GameObject.FindGameObjectWithTag(SysDefine.SYS_TAG_CANVAS);
 56             _TraUIScriptsNode = UnityHelper.FindTheChildNode(_GoCanvasRoot, SysDefine.SYS_SCRIPTMANAGER_NODE);
 57             //把本腳本實例,作為“腳本節點對象”的子節點。
 58             UnityHelper.AddChildNodeToParentNode(_TraUIScriptsNode,this.gameObject.transform);
 59             //得到“頂層面板”、“遮罩面板”
 60             _GoTopPanel = _GoCanvasRoot;
 61             _GoMaskPanel = UnityHelper.FindTheChildNode(_GoCanvasRoot, "_UIMaskPanel").gameObject;
 62             //得到UI攝像機原始的“層深”
 63             _UICamera = GameObject.FindGameObjectWithTag("_TagUICamera").GetComponent<Camera>();
 64             if (_UICamera != null)
 65             {
 66                 //得到UI攝像機原始“層深”
 67                 _OriginalUICameralDepth = _UICamera.depth;
 68             }
 69             else
 70             {
 71                 Debug.Log(GetType()+"/Start()/UI_Camera is Null!,Please Check! ");
 72             }
 73         }
 74 
 75         /// <summary>
 76         /// 設置遮罩狀態
 77         /// </summary>
 78         /// <param name="goDisplayUIForms">需要顯示的UI窗體</param>
 79         /// <param name="lucenyType">顯示透明度屬性</param>
 80         public void SetMaskWindow(GameObject goDisplayUIForms,UIFormLucenyType lucenyType=UIFormLucenyType.Lucency)
 81         {
 82             //頂層窗體下移
 83             _GoTopPanel.transform.SetAsLastSibling();
 84             //啟用遮罩窗體以及設置透明度
 85             switch (lucenyType)
 86             {
 87                     //完全透明,不能穿透
 88                 case UIFormLucenyType.Lucency:
 89                     print("完全透明");
 90                     _GoMaskPanel.SetActive(true);
 91                     Color newColor1=new Color(255/255F,255/255F,255/255F,0F/255F);
 92                     _GoMaskPanel.GetComponent<Image>().color = newColor1; 
 93                     break;
 94                     //半透明,不能穿透
 95                 case UIFormLucenyType.Translucence:
 96                     print("半透明");
 97                     _GoMaskPanel.SetActive(true);
 98                     Color newColor2 = new Color(220/255F, 220/255F, 220/255F, 50/255F);
 99                     _GoMaskPanel.GetComponent<Image>().color = newColor2; 
100                     break;
101                     //低透明,不能穿透
102                 case UIFormLucenyType.ImPenetrable:
103                     print("低透明");
104                     _GoMaskPanel.SetActive(true);
105                     Color newColor3=new Color(50/255F,50/255F,50/255F,200F/255F);
106                     _GoMaskPanel.GetComponent<Image>().color = newColor3; 
107                     break;
108                     //可以穿透
109                 case UIFormLucenyType.Pentrate:
110                     print("允許穿透");
111                     if (_GoMaskPanel.activeInHierarchy)
112                     {
113                         _GoMaskPanel.SetActive(false);
114                     }
115                     break;
116 
117                 default:
118                     break;
119             }
120 
121 
122 
123             //遮罩窗體下移
124             _GoMaskPanel.transform.SetAsLastSibling();
125             //顯示窗體的下移
126             goDisplayUIForms.transform.SetAsLastSibling();
127             //增加當前UI攝像機的層深(保證當前攝像機為最前顯示)
128             if (_UICamera!=null)
129             {
130                 _UICamera.depth = _UICamera.depth + 100;    //增加層深
131             }
132 
133         }
134 
135         /// <summary>
136         /// 取消遮罩狀態
137         /// </summary>
138         public void CancelMaskWindow()
139         {
140             //頂層窗體上移
141             _GoTopPanel.transform.SetAsFirstSibling();
142             //禁用遮罩窗體
143             if (_GoMaskPanel.activeInHierarchy)
144             {
145                 //隱藏
146                 _GoMaskPanel.SetActive(false);
147             }
148 
149             //恢復當前UI攝像機的層深 
150             if (_UICamera != null)
151             {
152                 _UICamera.depth = _OriginalUICameralDepth;  //恢復層深
153             }
154         }
155 
156 
157     }
158 }
View Code

 

關於上述定義的UIMaskMgr.cs 腳本代碼 ,筆者在“BaseUIForm.cs” 中做了封裝,使其可以在框架中自動管理,無需框架外客戶程序的處理。BaseUIForm.cs 代碼如下:

 1 /***
 2  * 
 3  *    Title: "SUIFW" UI框架項目
 4  *           主題: UI窗體的父類
 5  *    Description: 
 6  *           功能:定義所有UI窗體的父類。
 7  *           定義四個生命周期
 8  *           
 9  *           1:Display 顯示狀態。
10  *           2:Hiding 隱藏狀態
11  *           3:ReDisplay 再顯示狀態。
12  *           4:Freeze 凍結狀態。
13  *           
14  *                  
15  *    Date: 2017
16  *    Version: 0.1版本
17  *    Modify Recoder: 
18  *    
19  *   
20  */
21 using System.Collections;
22 using System.Collections.Generic;
23 using System.ComponentModel.Design;
24 using UnityEngine;
25 
26 namespace SUIFW
27 {
28     public class BaseUIForm : MonoBehaviour {
29         /*字段*/
30         private UIType _CurrentUIType=new UIType();
31 
32         /* 屬性*/
33         //當前UI窗體類型
34         public UIType CurrentUIType
35         {
36             get { return _CurrentUIType; }
37             set { _CurrentUIType = value; }
38         }
39 
40 
41         #region  窗體的四種(生命周期)狀態
42 
43         /// <summary>
44         /// 顯示狀態
45         /// </summary>
46         public virtual void Display()
47         {
48             this.gameObject.SetActive(true);
49             //設置模態窗體調用(必須是彈出窗體)
50             if (_CurrentUIType.UIForms_Type==UIFormType.PopUp)
51             {
52                 UIMaskMgr.GetInstance().SetMaskWindow(this.gameObject,_CurrentUIType.UIForm_LucencyType);
53             }
54         }
55 
56         /// <summary>
57         /// 隱藏狀態
58         /// </summary>
59         public virtual void Hiding()
60         {
61             this.gameObject.SetActive(false);
62             //取消模態窗體調用
63             if (_CurrentUIType.UIForms_Type == UIFormType.PopUp)
64             {
65                 UIMaskMgr.GetInstance().CancelMaskWindow();
66             }
67         }
68 
69         /// <summary>
70         /// 重新顯示狀態
71         /// </summary>
72         public virtual void Redisplay()
73         {
74             this.gameObject.SetActive(true);
75             //設置模態窗體調用(必須是彈出窗體)
76             if (_CurrentUIType.UIForms_Type == UIFormType.PopUp)
77             {
78                 UIMaskMgr.GetInstance().SetMaskWindow(this.gameObject, _CurrentUIType.UIForm_LucencyType);
79             }
80         }
81 
82         /// <summary>
83         /// 凍結狀態
84         /// </summary>
85         public virtual void Freeze()
86         {
87             this.gameObject.SetActive(true);
88         }
89 
90 
91         #endregion
92 
93 
94     }
95 }
View Code

 

 

以上所講解的是大體實現思路,還有很多的小細節由於時間關系沒有披露,所以特提供下載鏈接,供感興趣的開發者研究討論。歡迎大家提供進一步完善的思路與建議。

 

本游戲UI框架(截止到以上部分)下載參考鏈接: 鏈接:http://pan.baidu.com/s/1nv4plFV 密碼:6o0n

 

 

先講解到這,我們下次講解: 游戲UI框架設計(五):配置管理與日志系統

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM