Unity 学习笔记#5:UI 框架

Unity 学习笔记#5:UI 框架

Zahkrii Lv2

实现一个可扩展的简单 UI 框架,由 UI 管理器统一管理。

配图

UI 管理器 - UIManager

统一管理所有 UI 界面,包括 UI 的显示与关闭。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/// <summary>
/// UI 管理器
/// </summary>
internal class UIManager : Singleton<UIManager> // 单例
{
// UI 元素
private class UIElement
{
// UI资源 Prefab 路径
public string Resource;

// 是否缓存
public bool Cache;

// Cache = true,存入 Instance
public GameObject Instance;
}

// 存储所有已加载的 UI 预制体,以其 Type 为索引
private Dictionary<Type, UIElement> UIResources = new Dictionary<Type, UIElement>();

public UIManager()
{
// 加载 UI,每个 UI Prefab 必做,UIElement 表示一个 UI 界面预制体
UIResources.Add(typeof(UIElement), new UIElement() { Resource = "UI/UITest", Cache = true });
}

~UIManager()
{
}

/// <summary>
/// 显示 UI
/// </summary>
/// <typeparam name="T">需要显示的 UI</typeparam>
/// <returns>需要显示的 UI</returns>
public T Show<T>()
{
//可引入声音管理器播放声音
// SoundManager.Instance.PlaySound("ui_open");
Type type = typeof(T);

// 判断是否存在
if (UIResources.ContainsKey(type))
{
// 取出
UIElement info = UIResources[type];
// 如果已缓存入实例,直接激活
if (info.Instance != null)
{
info.Instance.SetActive(true);
}
else // 否则读取Prefab
{
UnityEngine.Object prefab = Resources.Load(info.Resource);
if (prefab == null)
{
return default(T);
}
info.Instance = (GameObject)GameObject.Instantiate(prefab);
}
return info.Instance.GetComponent<T>();
}
return default(T);
}

/// <summary>
/// 关闭UI
/// </summary>
/// <param name="type">需要关闭的 UI</param>
public void Close(Type type)
{
//可引入声音管理器播放声音
// SoundManager.Instance.PlaySound("ui_close");
if (UIResources.ContainsKey(type))
{
UIElement info = UIResources[type];
if (info.Cache)
{
info.Instance.SetActive(false);
}
else
{
GameObject.Destroy(info.Instance);
info.Instance = null;
}
}
}
}

抽象父类 - UIWindow

所有 UI 的父类,每个 UI 窗口都得继承自 UIWindow,包含几个常用方法(当点击关闭按钮,当点击确定按钮),子类可以不用重写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/// <summary>
/// 所有UI的父类,包含几个常用方法,子类可以不用重写
/// </summary>
public abstract class UIWindow : MonoBehaviour
{
// Close 委托
public delegate void CloseHandler(UIWindow sender, WindowResult result);
// Close 事件
public event CloseHandler OnClose;

public virtual System.Type Type
{
get { return this.GetType(); }
}

// 窗口返回结果
public enum WindowResult
{
None = 0,
Yes,
No,
}

/// <summary>
/// 关闭窗口时调用
/// </summary>
/// <param name="result">返回结果</param>
public void Close(WindowResult result = WindowResult.None)
{
UIManager.Instance.Close(this.Type);
if (this.OnClose != null)
this.OnClose(this, result);
this.OnClose = null;
}

/// <summary>
/// 当点击关闭按钮
/// </summary>
public virtual void OnCloseClick()
{
this.Close();
}

/// <summary>
/// 当点击确定按钮
/// </summary>
public virtual void OnYesClick()
{
this.Close(WindowResult.Yes);
}
}

UI 元素 - 继承自 UIWindow

这里可以重写父类方法,或者实现自定义功能,此脚本需绑定在一个 UI 预制体上。

1
2
3
4
5
6
7
8
9
10
11
12
public class UIElement : UIWindow
{
// Start is called before the first frame update
private void Start()
{
}

// Update is called once per frame
private void Update()
{
}
}

显示 UI 元素

使用以下代码:

UIManager.Instance.Show<UIElement>();

因为 Show<T>() 有返回值 T,可以这样写:

UIElement element = UIManager.Instance.Show<UIElement>();

这样就能拿到 UIElement 做一些有趣的事了。例如:

1
2
3
4
5
6
7
8
9
10
11
UIElement element = UIManager.Instance.Show<UIElement>();
// 调用 UIElement 里的方法
element.SetTitle();
// 指定点击关闭按钮后的处理方法
element.OnClose += element_OnClose;

private void element_OnClose(UIWindow sender, UIWindow.WindowResult result)
{
// 一些事情
//获取UIElement等 (sender as UIElement).name;
}
  • 标题: Unity 学习笔记#5:UI 框架
  • 作者: Zahkrii
  • 创建于 : 2022/06/04 17:08:55
  • 更新于 : 2024/06/24 23:52:32
  • 链接: https://zahkrii.github.io/2022/06/04/unity-notes-5/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。