赞
踩
UI框架中的 UIManager
管理场景中所有的面板, 控制面板之间的跳转.
先搭建好所有的UI界面, 并保存为prefab
json: json用于描述资料结构,有两种结构存在:
{
开始,并以}
结束。每个名称/值对之间使用:
分区。[
开始,并以]
结束。数组成员之间使用,
分区。数组成员具体的格式如下:
:
隔开,一般的形式是:{name:value}
UIPanelType.json
: 保存这个工程所有的UI面板类型及其相应的prefab的路径, 此时主要该文件和prefab文件都需要位于Resources
文件夹路径下
- {
- "infoList":
- [
- {"panelTypeString":"ALERT_PANEL",
- "path":"AlertPanel"},
-
- {"panelTypeString":"CONNECT_PANEL",
- "path":"ConnectPanel"},
-
- {"panelTypeString":"HOME_PANEL",
- "path":"HomePanel"},
-
- {"panelTypeString":"WELCOME_PANEL",
- "path":"WelcomePanel"}
- ]
- }
UIPanelType.cs
: 保存这个工程所有的UI面板类型
- public enum UIPanelType {
- ALERT_PANEL,
- CONNECT_PANEL,
- HOME_PANEL,
- WELCOME_PANEL
- }
JsonUtility
的使用:FromJson | Create an object from its JSON representation. |
---|---|
FromJsonOverwrite | Overwrite data in an object by reading from its JSON representation. |
ToJson | Generate a JSON representation of the public fields of an object. |
注意json中的key值和所对应的unity类中的字段名要保持一致
-
- [Serializable]
- public class UIPanelInformation : ISerializationCallbackReceiver {
- [NonSerialized]
- public UIPanelType panelType;
- public string panelTypeString;
- public string path;
-
- public void OnAfterDeserialize() {
- //反序列化之后, 将一个或多个枚举字符串表示(panelTypeString)转换成等效的枚举对象(UIPanelType)。
- UIPanelType type = (UIPanelType)Enum.Parse(typeof(UIPanelType), panelTypeString);
- panelType = type;
- }
- public void OnBeforeSerialize() {
- //啥都不用做
- }
- }
-
- [Serializable]
- public class UIPanelTypeJson {
- //用来储存json对象所对应的类的列表
- public List<UIPanelInformation> infoList;
- }
-
-
在UIManager.cs
中 :
- private void ParseUIPanelTypeJson() {
- mPanelPathDictionary = new Dictionary<UIPanelType, string>();
- TextAsset textAsset = Resources.Load<TextAsset>("Demo1/UIPanelType");
- //将json对象转化为UIPanelTypeJson类
- UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(textAsset.text);
- foreach (UIPanelInformation info in jsonObject.infoList) {
- mPanelPathDictionary.Add(info.panelType, info.path);
- }
- }
为什么使用virtual
关键字而不是abstract
关键字来修饰?
mPanelPathDictionary
: 路径字典, 解析保存所有的面板信息(枚举类型和prefab路径)mPanelPool
: 实例对象池, 保存所有已实例化的面板mPanelStack
: 页面栈, 管理各个页面切换任务主要方法:
PushPanel(UIPanelType panelType)
: 新增一个页面, 此时当前页面需要被暂停PushPanel(UIPanelType panelType, bool isPopCurrentPanel)
: 新增一个页面, 此时当前页面或所有页面需要被关闭BackToLastPanel
: 如果mPanelStack.Count
为1, 则提示退出程序; 如果不为1, 则弹出当前页面, 并显示此时mPanelStack
栈顶页面了解一下: CanvasGroup 组件, 属性有:
alpha | Set the alpha of the group.设置该组的透明度。 |
---|---|
blocksRaycasts | Does this group block raycasting (allow collision).该组是否忽略投射(允许碰撞)。 |
ignoreParentGroups | Should the group ignore parent groups?是否忽略父物体组? |
interactable | Is the group interactable (are the elements beneath the group enabled).是否打开交互(在该组之下启用该元素)。 |
CanvasGroup
的典型用途是:
CanvasGroup
并控制其Alpha
属性来实现整体淡入或淡出。CanvasGroup
组件中Interactable属性设置为false,从而使子物体一组控件不可交互(“变灰”)。CanvasGroup
组件放置在元素或其父项之一上并将其BlockBlockcast
属性设置为false,使一个或多个UI元素不会阻挡鼠标事件(即射线可穿透它)。参考解决方案:
组件要求:
相关代码为:
- [RequireComponent(typeof(CanvasGroup))]
- public class BasePanel : MonoBehaviour {
- protected CanvasGroup canvasGroup;
- protected virtual void Awake() {
- canvasGroup = gameObject.GetComponent<CanvasGroup>();
-
- //其它代码
- }
-
- private void SetPanelInteractable(bool isInteractable) {
- if (isInteractable ^ canvasGroup.interactable) canvasGroup.interactable = isInteractable;
- }
-
- //其它代码
- }
-
在游戏运行中如何使得新创建的面板显示在最上面?如何修改UGUI的显示层级?
了解一下: UGUI物体的渲染顺序
SetAsFirstSibling
:移动到所有兄弟节点的第一个位置(Hierarchy同级最上面,先渲染,显示在最下面)SetAsLastSibling
:移动到所有兄弟节点的最后一个位置(Hierarchy同级最下面,后渲染,显示在最上面)GetSiblingIndex
:获得该元素在当前兄弟节点层级的位置SetSiblingIndex
:设置该元素在当前兄弟节点层级的位置参考解决方案:
gameObject.transform.SetAsLastSibling();
留意Hierarchy窗口
页面重新出现的时候, Awake
和Start
函数内的数据刷新不了?
了解一下Unity脚本生命周期:
测试一下, 在Awake
, OnEnable
, Start
, OnDisable
, OnEnter
, OnExit
函数里面加上Debug.Log
输出, 结果如图:
AlertPanel.cs
的函数调用顺序为:
可见, Awake
, Start
函数只调用一次, 因此, 每次显示和隐藏页面时的数据操作,可以通过OnEnter
, OnExit
这两个方法来实现
参考解决方案:
OnEnter
, OnExit
函数里面进行关于即时数据的操作;Awake
, Start
里面进行各种初始化操作注意:
切换时当前场景内的物体都会被清空, 但我们可以通过DontDestroyOnLoad
来保留UIManager
单例, 同时将 mPanelPool
和mPanelStack
清空就好了
- /// <summary>
- /// 实例化UIManager
- /// </summary>
- /// <returns></returns>
- private static UIManager GetInstance() {
- if (sInstanceUiManager == null) {
- var go = new GameObject("UIManager");
- sInstanceUiManager = go.AddComponent<UIManager>();
- //如果有场景切换
- DontDestroyOnLoad(go);
- }
- return sInstanceUiManager;
- }
-
- /// <summary>
- /// 切换场景前,调用该方法来清空当前场景的数据
- /// </summary>
- public void RefreshDataOnSwitchScene() {
- mPanelPathDictionary.Clear();
- mPanelStack.Clear();
- }
如何切换场景?
- UIManager.Instance.RefreshDataOnSwitchScene();
- SceneManager.LoadScene("NewScene");
序列化可以用于跨平台。实际上就是把一段数据翻译成(序列化)比较底层的语言(如汇编、机器语言),而基于这个底层语言再可以翻译(反序列化)成多种上一层的语言。
Unity会自动序列化所有你自己写的脚本组件(Scriptable Object), 重载新的程序集,并且重新创建你的脚本组件。简单的说,序列化后,数据就可以被保存了。Unity序列化过程不走.NET的方法,而是Unity内部的方法。
GitHub - jingangxin36/MyUITools: Unity实现基于UGUI的简易UI框架
--------------------- 本文来自 jingangxin36 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/jingangxin666/article/details/80092801?utm_source=copy
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。