Unity的UI框架

UI框架

UI框架的含义

含义:UI框架用于管理场景中所有的面板,负责控制面板之间的跳转

UI框架的意义

1、随着游戏系统的复杂化,UI控件越来越多,各个UI之间的直接通讯,已经UI与GameObject之间的关系会越来越复杂
2、代码耦合性会很强

UI框架的实例

1、框架面板的设计

MainMenuPanel:主菜单面板
BagPanel:背包面板
ItemMessagePanel:物品信息面板
ShopPanel:商城面板
SkillPanel:技能面板
SystemPanel:系统面板
TaskPanel:技能面板

在这里插入图片描述
我们将设计好的面板做成预制体,放在Resources的目录下。

2、Json数据的读取

UIPanelInfo.json

{
  "infoList":
  [

    {
      "panelTypeString": "ItemMessage",
      "path": "UIPanel/ItemMessagePanel"
    },

    {
      "panelTypeString": "BagPanel",
      "path": "UIPanel/BagPanel"
    },

    {
      "panelTypeString": "MainMenu",
      "path": "UIPanel/MainMenuPanel"
    },

    {
      "panelTypeString": "Shop",
      "path": "UIPanel/ShopPanel"
    },

    {
      "panelTypeString": "Skill",
      "path": "UIPanel/SkillPanel"
    },

    {
      "panelTypeString": "System",
      "path": "UIPanel/SystemPanel"
    },
    {
      "panelTypeString": "Task",
      "path": "UIPanel/TaskPanel"
    }

  ]
}
将所有信息作为一个infolist类的对象

UIPanelType

public enum UIPanelType 
{
    BagPanel,
    ItemMessage,
    MainMenu,
    Shop,
    Skill,
    System,
    Task,
}

UIManager

public class UIManager 
{
    private Dictionary<UIPanelType, string> panelPathDicr;//存储所有面板Prefab的路径,UIPanelType类型,string用于存储路径

    private UIManager()
    {
        ParseUIPanelTypeJson();//调用ParseUIPanelTypeJson方法解析Json文件
    }
    //单例化
    private static UIManager instance;

    public static UIManager GetInstance()
    {
        if (instance == null)
        {
            instance = new UIManager();
        }
        return instance;
    }

    [Serializable]
    class UIPanelTypeJson//将Json文件视作一个整体,直接将其转换为List<UIPanelInfo>
    {
        public List<UIPanelInfo> infoList;
    }



    //解析Json文件
    private void ParseUIPanelTypeJson()
    {
        panelPathDicr = new Dictionary<UIPanelType, string>();//生成一个字典
        TextAsset ta = Resources.Load<TextAsset>("UIPanelType");//加载Json文件中的UIPanelType信息

       UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);//JsonUtility——工具类,将Json中的文件解析为对象,ta.text就是JSON信息,将JSON信息转换为UIPanelTypeJson类

        //总的意思就是将JSON文件转换为UIPanelTypeJson类,而UIPanelTypeJson类中则是List<UIPanelInfo>,并其字段infoList对应JSON文件的类名

        foreach (UIPanelInfo info in jsonObject.infoList)//遍历UIPanelInfo的数组
        {
            //Debug.Log(info.panelType);
            panelPathDicr.Add(info.panelType, info.path);//这里的info相对于生成一个jsonObject.infoList,因此info就是数组中的一个元素。
            //将对象加入到字典当中去
        }
    }
    public void Test()//测试
    {
        string path;
        panelPathDicr.TryGetValue(UIPanelType.Shop, out path);
        Debug.Log(path);
    }
}

UIPanelInfo

[Serializable]
public class UIPanelInfo:ISerializationCallbackReceiver
    
    //将UIPanelInfo进行序列化,[Serializable]标签就是运行下面字段可进行读盘和写盘,负责与Json文件向对应,读取Json的文件,传递数据,可以避免直接修改Json文件
{
    [NonSerialized]
    public UIPanelType panelType;//记录Json文件中的panelType对象

    //由于无法直接解析UIPanelType,所有使用string来接受Json数据
    public string panelTypeString;
        
    //{第一种方式转换方式。
    //    get
    //    {
    //        return panelType.ToString();
    //    }
    //    set 
    //    {
    //      UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), value);
    //        panelType = type;
    //    }
    //}
    public string path;//记录path的路径字段


    //反序列化 从文本信息到对象
    public void OnAfterDeserialize()//每次反序列化后就会调用
    {
        UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);
                panelType = type;//将文本中的panelTypeString强制转换成UIPanelType
    }

    public void OnBeforeSerialize()//每次序列化之前调用这个方法
    {
       
    }
}

分析:
首先
1、UIPanelType类
作为一个枚举类,用于记录各个面板,保存面板的类型
2、UIPanelType.json
这是一个Json文件,用于存储各个面板的具体信息
例如:
    "panelTypeString": "MainMenu",
    "path": "UIPanel/MainMenuPanel"
panelTypeString保存对象
path保存路径
3、UIPanelInfo
负责与Json文件向对应
    public UIPanelType panelType;//记录Json文件中的panelType对象
    public string path;//记录path的路径字段

这里要将其设置为可序列化的状态[Serializable],让这个类可以读盘与写盘,方便后期对信息进行修改
,也可以避免直接修改Json文件
4、UIManger
是UI框架的核心,负责管理各种框架
第一步,将其设置为单例模式
第二步,将Json文件解析
第三步,使用UIPanelInfo的数组来接受Json文件的信息
第四步,遍历UIPanelInfo数组,并将其中的数据加入字典当中

其中有两个关键点。
第一,加载Json文件,并将文件解析为UIPanelInfo对象的数组
第二,遍历数组,并加入字典中,方便以后对其数据进行各种操作


3、框架逻辑设计

在这里插入图片描述
BasePanel的设计

public class BasePanel : MonoBehaviour
{
    /// <summary>
    /// 界面被显示出来
    /// </summary>
    public virtual void OnEnter()
    { }
    /// <summary>
    /// 界面暂停
    /// </summary>
    public virtual void OnPause()
    { }
    /// <summary>
    /// 界面继续
    /// </summary>
    public virtual void OnResume()
    { }
    /// <summary>
    /// 界面不显示,退出这个界面,界面被关闭
    /// </summary>
    public virtual void OnExit()
    { }

}

BagPanel继承BasePanel

public class BagPanel:BasePanel
{
    private CanvasGroup canvasGroup;
    private void Start()
    {
        if (canvasGroup == null)
        {
            canvasGroup = GetComponent<CanvasGroup>();
        }

        
    }
    /// <summary>
    /// 处理页面的关闭
    /// </summary>
    public override void OnExit()
    {
       // canvasGroup.alpha = 0;
        canvasGroup.blocksRaycasts = false;

    
        transform.DOLocalMoveX(600, 0.5f).OnComplete(() => canvasGroup.alpha = 0);
    }
    public void OnClosePanel()
    {
        UIManager.GetInstance().PopPanel();
    }
    public override void OnEnter()
    {
        if (canvasGroup == null)
        {
            canvasGroup = GetComponent<CanvasGroup>();
        }
        canvasGroup.alpha = 1;
        canvasGroup.blocksRaycasts = true;

        //弹出动画
        Vector3 temp = transform.localPosition;
        temp.x = 600;
        transform.localPosition = temp;
        transform.DOLocalMoveX(0, 0.5f);
    }
    public override void OnPause()
    {
        canvasGroup.blocksRaycasts = false;
    }
    public override void OnResume()
    {
        canvasGroup.blocksRaycasts = true;
    }
    public void OnItemButtonClick()
    {
        UIManager.GetInstance().PushPanel(UIPanelType.ItemMessage);
    }
}

完善后的UIManager

public class UIManager 
{
    private Transform canvasTransform;
    private Transform CanvasTransform
    {
        get 
        {
            if (canvasTransform == null)
            {
                canvasTransform = GameObject.Find("Canvas").transform;
               
            }
            return canvasTransform;
        }
  
    }

    private Dictionary<UIPanelType, string> panelPathDicr;//存储所有面板Prefab的路径,UIPanelType类型,string用于存储路径

    private Dictionary<UIPanelType, BasePanel> panelDict;//保存所有面板的游戏物体身上的BasePanel组件

    private Stack<BasePanel> panelStacks;

    /// <summary>
    /// 把某个页面入栈,触发相应方法,并显示在界面上
    /// </summary>
    public void PushPanel(UIPanelType panelType)
    {
        if (panelStacks == null)
        {
            panelStacks = new Stack<BasePanel>();
        }
        //判断一下栈里面是否有页面
        if (panelStacks.Count > 0)
        {
            BasePanel topPanel = panelStacks.Peek();
            topPanel.OnPause();
        }
        BasePanel panel = GetPanel(panelType);
        panel.OnEnter();
        panelStacks.Push(panel);
    }
    /// <summary>
    /// 出栈,把页面从界面上移除
    /// </summary>
   public void PopPanel()
    {
        if (panelStacks == null)
        {
            panelStacks = new Stack<BasePanel>();
        }
        //BasePanel panel = GetPanel(panelType);
        if (panelStacks.Count <= 0)
        {
            return;
        }
        BasePanel topPanel = panelStacks.Pop();
        topPanel.OnExit();
        if (panelStacks.Count <= 0) return;
        BasePanel topPanel2 = panelStacks.Peek();
        topPanel2.OnResume();



    }
  

    /// <summary>
    /// 根据面板类型,得到实例化的面板
    /// </summary>
    /// <returns></returns>
    public BasePanel GetPanel(UIPanelType panelType)
    {
        if (panelDict == null)
        {
            panelDict = new Dictionary<UIPanelType, BasePanel>();
        }
      
        //BasePanel panel;
        //panelDict.TryGetValue(panelType, out panel);//TODO


        BasePanel panel = panelDict.TryGet(panelType);


        if (panel == null)
        {
            //如果找不到,就找这个面板的Prefab的路径,然后去根据Prefab去实例化面板
            //string path;
            //panelPathDicr.TryGetValue(panelType, out path);

            string path = panelPathDicr.TryGet(panelType);//字典对象的值是已经决定了的,所以不需要使用泛型而dict对象就是panelPathDicr,不需要再赋值字典
            var pan = Resources.Load(path);
            GameObject instPanel = GameObject.Instantiate(pan) as GameObject;//实例化
            instPanel.transform.SetParent(CanvasTransform, false);//TODO false表示局部位置,而非全局位置
            panelDict.Add(panelType, instPanel.GetComponent<BasePanel>());
            return instPanel.GetComponent<BasePanel>();
               
        }
        else
        {
            return panel;
        }

    }


    private UIManager()
    {
        ParseUIPanelTypeJson();//调用ParseUIPanelTypeJson方法解析Json文件
    }
    //单例化
    private static UIManager instance;

    public static UIManager GetInstance()
    {
        if (instance == null)
        {
            instance = new UIManager();
        }
        return instance;
    }

    [Serializable]
    class UIPanelTypeJson//将Json文件视作一个整体,直接将其转换为List<UIPanelInfo>
    {
        public List<UIPanelInfo> infoList;
    }



    //解析Json文件
    private void ParseUIPanelTypeJson()
    {
        panelPathDicr = new Dictionary<UIPanelType, string>();//生成一个字典
        TextAsset ta = Resources.Load<TextAsset>("UIPanelType");//加载Json文件中的UIPanelType信息

       UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);//JsonUtility——工具类,将Json中的文件解析为对象,ta.text就是JSON信息,将JSON信息转换为UIPanelTypeJson类

        //总的意思就是将JSON文件转换为UIPanelTypeJson类,而UIPanelTypeJson类中则是List<UIPanelInfo>,并其字段infoList对应JSON文件的类名

        foreach (UIPanelInfo info in jsonObject.infoList)//遍历UIPanelInfo的数组
        {
            //Debug.Log(info.panelType);
            panelPathDicr.Add(info.panelType, info.path);//这里的info相对于生成一个jsonObject.infoList,因此info就是数组中的一个元素。
            //将对象加入到字典当中去
        }
    }
    public void Test()//测试
    {
        string path;
        panelPathDicr.TryGetValue(UIPanelType.Shop, out path);
        Debug.Log(path);
    }
}

分析
1、BasePanel作为基类被其他的具体类继承
而BasePanel中的方法为

 OnEnter()——进入
 OnPause()——暂停
 OnResume()——恢复
 OnExit()——退出
 
 2、具体的类在继承的基础上,进行具体的修改,添加事件
 3、UIManager则负责使用“栈”来对不同页面进行管理
   

  • 10
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity中弹出提示框可以使用Unity自带的UI组件,具体操作如下: 1. 创建一个Canvas对象:在Hierarchy视图中右键点击Create Empty,然后在Inspector视图中点击Add Component,选择Canvas。 2. 创建一个Panel对象:在Hierarchy视图中右键点击Canvas,选择UI -> Panel。 3. 在Panel对象上添加一个Text组件:在Hierarchy视图中选中Panel对象,在Inspector视图中点击Add Component,选择Text。 4. 编辑Text组件的内容和样式:在Inspector视图中选择Text组件,可以修改Text的内容、字体、字号、颜色等属性。 5. 创建一个Button对象:在Hierarchy视图中右键点击Panel,选择UI -> Button。 6. 给Button对象添加一个事件:在Inspector视图中选择Button对象,点击Add Component,选择Button。 7. 编写弹出提示框的代码:在脚本中使用Unity自带的弹出框方法,例如: ```csharp using UnityEngine; using UnityEngine.UI; public class Example : MonoBehaviour { public Text messageText; public void ShowMessageBox() { string message = messageText.text; Debug.Log(message); // 弹出提示框 MessageBox.Show(message); } } ``` 在这个示例代码中,我们定义了一个Text类型的变量messageText表示要显示的提示信息,然后在ShowMessageBox()方法中获取messageText的文本内容,并调用Unity自带的MessageBox.Show()方法弹出提示框。 8. 将脚本挂载到Button对象上:在Hierarchy视图中选择Button对象,在Inspector视图中点击Add Component,选择Example脚本。 9. 运行程序并测试:在Unity编辑器中点击Play按钮运行程序,然后点击Button按钮测试弹出提示框是否正常显示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值