这套UI框架是基于Unity目前主流的UGUI的,虽说目前Unity官方正在开发新的UIToolkit,但是目前还是预览版。这个框架我在多个项目中使用了,内容比较简单、实用,在此记录一下,方便以后使用。
一、首先这个框架是细分到一个个UI窗口上的,所以第一个类是WindowBase
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class WindowBase : MonoBehaviour { //皮肤路径 public string skinPath; //皮肤 public GameObject skin; //层级 public UIManager.Layer layer = UIManager.Layer.Panel; //初始化 public void Init(){ //皮肤 GameObject skinPrefab = Resources.Load<GameObject>(skinPath); skin = (GameObject)Instantiate(skinPrefab); } //关闭 public void Close(){ string name = this.GetType().ToString(); UIManager.Close(name); } //初始化时 public virtual void OnInit(){ } //显示时 public virtual void OnShow(params object[] para){ } //关闭时 public virtual void OnClose(){ } }
二、第二个类是UIManager
using System.Collections.Generic; using UnityEngine; //UIManager不用继承于Monobehaviour,里面都是静态方法 public class UIManager { //Layer对应不同的层级 public enum Layer{ Panel, Tip,//一般用作弹框 } //层级列表 private static Dictionary<Layer, Transform> layers = new Dictionary<Layer, Transform>(); //面板列表 public static Dictionary<string, WindowBase> panels = new Dictionary<string, WindowBase>(); //结构 public static Transform canvas; //初始化 public static void Init(){ canvas = GameObject.Find("Canvas").transform; Transform panel = canvas.Find("Panel"); Transform tip = canvas.Find("Tip"); layers.Add(Layer.Panel, panel); layers.Add(Layer.Tip, tip); } //打开面板 public static void Open<T>(params object[] para) where T:WindowBase{ //已经打开 string name = typeof(T).ToString(); if (panels.ContainsKey(name)){ return; } //组件 WindowBase panel = canvas.gameObject.AddComponent<T>(); panel.OnInit(); panel.Init(); //父容器 Transform layer = layers[panel.layer]; panel.skin.transform.SetParent(layer, false); //列表 panels.Add(name, panel); //OnShow panel.OnShow(para); } //关闭面板 public static void Close(string name){ WindowBase panel = panels[name]; //没有打开 if (panel == null){ return; } //OnClose panel.OnClose(); //列表 panels.Remove(name); //销毁 GameObject.Destroy(panel.skin); Component.Destroy(panel); } //关闭所有 //在跳转场景时候删除了所有ui所以要closeall,为了防止再次进入该场景时候字典中重复添加。但是如果用的是dontdestroyonload就不需要了 public static void CloseAll() { foreach(var i in panels) { WindowBase panel = i.Value; //没有打开 if (panel == null){ return; } panel.OnClose(); //销毁 GameObject.Destroy(panel.skin); Component.Destroy(panel); } panels.Clear(); layers.Clear(); } }
三、完成上面两个类,我的框架的主体基本就有了,为了对框架有一个初始化,我们还需要写一个程序入口类,并且在该类中对UIManager初始化。
using System.Collections; using System.Collections.Generic; using UnityEngine; //APP入口 public class MainEntry : MonoBehaviour { void Start() { UIManager.Init(); UIManager.Open<MainWindow>(); } private void OnDestroy() { UIManager.CloseAll(); } }
四、接下来我们完成一个主UI的实现。
第一步是在Inspector窗口中添加我们的canvas,然后再创建两个子物体分别命名为Plane和Tip用来对应我们在UIManager中定义的两种层级,同时把自动生成的EventSystem也放在Canvas底下。效果如图所示。
然后再来制作我们的第一个UI界面——MainUI,这个界面很简单,只有几个按钮,如图所示,值得注意的是要把这个界面的根节点设置为跟随父级大小。最后我们把这个UI制作成预制体,放在我们的Resources文件夹中,方便我们使用代码加载。
然后就是写我们的UI逻辑代码了。我是在OnInit方法中设置预制体的路径和层级,在OnShow方法中对UI逻辑初始化。
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; //主面板 public class MainWindow : WindowBase { private Button InfoButton; private Button CreateButton; private Button ExitButton; public override void OnInit() { base.OnInit(); skinPath = "UIPrefab/MainPanel"; layer = UIManager.Layer.Panel; } public override void OnShow(params object[] para) { base.OnShow(para); InfoButton = skin.transform.Find("Upper/InfoButton").GetComponent<Button>(); CreateButton = skin.transform.Find("Upper/CreateButton").GetComponent<Button>(); ExitButton = skin.transform.Find("Upper/ExitButton").GetComponent<Button>(); InfoButton.onClick.AddListener(InfoButtonClick); CreateButton.onClick.AddListener(CreateButtonClick); ExitButton.onClick.AddListener(ExitButtonClick); } public override void OnClose() { base.OnClose(); } private void InfoButtonClick() { UIManager.Open<CreatePanel>(); } private void CreateButtonClick() { UIManager.Open<WithItemPanel>(); } private void ExitButtonClick() { string tip = "是否关闭?"; Action callback = new Action(CloseAppCallback); UIManager.Open<PopupPanel>(tip,callback); } private void CloseAppCallback() { print("当前程序正在退出!"); Application.Quit(); } }
我在MainEntry中已经把打开这个窗口的代码已经写上了。
UIManager.Open<MainWindow>();
这个时候我们运行程序就回打开我们的MainUI了。
框架到此就结束了,目前来说这些功能已经能够满足我们做一些中小型项目的需求了,并且使用起来也很方便。我也不想把它扩展的很庞大复杂。
这里是源码:下载地址