这套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了。
框架到此就结束了,目前来说这些功能已经能够满足我们做一些中小型项目的需求了,并且使用起来也很方便。我也不想把它扩展的很庞大复杂。
这里是源码:下载地址