赞
踩
UI管理器用于管理全局的UI实体,以省去手动创建UI实例、销毁UI实例等一系列操作,他可以在非常方便且省去不必要的开销优势下,让你条例清晰的组织和管控好任何复杂的UI结构。
UI系统有三种类型的UI,分别是Overlay(屏幕空间),Camera(摄像机空间),World(世界空间),每一个UI实体都可以标记其所属的类型,且每一个UI实体的根不需要是一个完整的Canvas,只需要是一个Panel,或者一个Image,甚至一个空的RectTransform就可以。
创建任意一个UGUI控件,并创建成预制体就可以了,这就是我们的UI实体(如下的GamePanel)。
每一个UI实体都由一个UI逻辑类所持有,且只能是一对一的关系,如果你的设计文档中不满足这个要求(比如某个UI逻辑类必须拥有两个UI实体才能实现业务需求),那请你重新设计UI结构(比如尝试着将这两个UI实体合并为一个,或者为另一个多余的实体重新设计一个UI逻辑类)。
新建一个UI逻辑类,必须满足以下条件:
1.继承至UILogicResident或者UILogicTemporary
2.标记特性UIResource
推荐使用快捷创建方式:
Project界面右键 -> Create -> HTFramework -> C# UILogicResident Script
如下图,我新建了一个名为UILogicGame的逻辑类,他持有的实体为上文创建的GamePanel:
/// <summary> /// 新建UI逻辑类 /// </summary> [UIResource("AssetBundleName", "AssetPath", "GamePanel", UIType.Overlay)] public class UILogicGame : UILogicResident { /// <summary> /// 初始化 /// </summary> public override void OnInit() { base.OnInit(); } /// <summary> /// 打开UI /// </summary> public override void OnOpen(params object[] args) { base.OnOpen(args); } /// <summary> /// 置顶UI /// </summary> public override void OnPlaceTop() { base.OnPlaceTop(); } /// <summary> /// 关闭UI /// </summary> public override void OnClose() { base.OnClose(); } /// <summary> /// 销毁UI /// </summary> public override void OnDestroy() { base.OnDestroy(); } /// <summary> /// UI逻辑刷新 /// </summary> public override void OnUpdate() { base.OnUpdate(); } }
1.UIResource特性标记了此UI逻辑类所指向的UI实体。
第一个参数:AssetBundleName为UI实体所打入的AB包名称;
第二个参数:AssetPath为UI实体在AB包中的路径(必须指明后缀,以便于Editor模式下加载);
第三个参数:ResourcePath为UI实体在Resources中的路径;
第四个参数:UIType为UI实体的类型。
第五个参数:DomainName为世界UI所属的域名。
注意:世界UI可以有多个Canvas根节点,在这里一个Canvas就对应一个域,以string类型的名称区分,每一个世界UI必须属于一个域。
注意:当资源加载方式采用AssetBundle方式时,参数1和参数2有效;当资源加载方式采用Resources方式时,参数3有效。
2.OnInit():UI实体创建成功后呼叫一次,若中途销毁UI,再次创建会重新呼叫。
3.OnOpen(params object[] args):UI打开后呼叫一次。
4.OnPlaceTop():UI置顶后呼叫一次。
5.OnClose():UI关闭后呼叫一次。
6.OnDestroy():UI销毁前呼叫一次。
7.OnUpdate():UI处于打开状态时,每帧呼叫。
注意:UI的逻辑类型分为两类,常驻UI(UILogicResident),非常驻UI(UILogicTemporary),两者之间的主要区别:
1.任何非常驻UI的层级 永远> 任何常驻UI的层级;
(也即是,非常驻UI永远会遮挡常驻UI,所以类似于全屏遮挡的提示、警告之类的可以定义为非常驻UI)
2.常驻UI可以共存,非常驻UI只能同时打开一个;
(也即是,当打开新的非常驻UI,则上一个显示的非常驻UI会自动关闭)
3.只有常驻UI可以被置顶;
写好了UI逻辑类,并做好了UI实体,直接调用框架接口就可以打开并显示UI了,不需要手动去管理UI逻辑类和UI实体的创建和销毁过程:
//打开一个UI
Main.m_UI.OpenUI<UILogicGame>();
也可以在协程方法中打开多个UI,并等待这些UI打开完成再进行后续指令:
private IEnumerator OpenUI()
{
//等待打开一个UI
yield return Main.m_UI.OpenUI<UILogicGame>();
//等待打开一个UI
yield return Main.m_UI.OpenUI<UIError>();
}
不过,必须在框架UI模块的编辑器面板启用该类型的UI,才能进行正常的打开等操作:
当然,在首次打开UI时,会经历加载实例和初始化的过程,可能较慢,如果无法等待这点时间,可以提前预加载UI:
//注意,预加载完成后会呼叫 OnInit 方法
//预加载一个UI
Main.m_UI.PreloadingUI<UILogicGame>();
被关闭的UI依然存在于内存中,只是不可见了:
//关闭一个UI
Main.m_UI.CloseUI<UILogicGame>();
若这个UI长时间不再使用,需要清理出内存,可以销毁UI:
//销毁一个UI
Main.m_UI.DestroyUI<UILogicGame>();
置顶一个常驻UI:
//置顶一个处于打开状态的常驻UI
Main.m_UI.PlaceTop<UILogicGame>();
在UI逻辑类中获取UI实体,只需要调用UIEntity字段就可以了:
/// <summary>
/// 初始化
/// </summary>
public override void OnInit()
{
UIEntity.GetComponentByChild<Text>("Title").text = "Game";
}
比如我要获取UI实体下的某一个GameObject,某一个组件,也可以使用InjectPath
依赖注入,比如此处我要获取Icon2对象:
代码中这样写:
public class UIGame : UILogicResident { //参数为路径,比如这里的:Icon1/Icon2 [InjectPath("Icon1/Icon2")] private GameObject _icon2; //也可以为组件注入依赖,比如这里的:Transform [InjectPath("Icon1/Icon2")] private Transform _icon2Tran; /// <summary> /// 初始化 /// </summary> public override void OnInit() { base.OnInit(); //这里_icon2 、_icon2Tran已注入依赖,可以直接使用 } }
根据一个UI逻辑类对应一个UI实体的关系,每一个UI逻辑类所持有的UI实体由UIResource特性标记,但在某些时候,对于一些简单的程序,我们既不想使用AB包模式,也不想动态Resources加载,我们就想让某个UI逻辑类使用某个特定的UI实体。
这就需要使用Define UI了,在检视面板可以直接指定某个UI逻辑类使用某个UI实体,该UI实体可以是Scene中的对象,也可以是Project中的预制体。
如下,我强制定义了UILevelPanel界面始终使用Level1作为UI实体,无论他的UIResource标记如何改变。
【Unity】 HTFramework框架(三十九)UI的数据驱动模式。
【Unity】 HTFramework框架(五十)【进阶篇】UI界面业务代码拆解,降低强耦合的利器。
在编辑器中运行时将会出现运行时检视面板(Runtime Data),主要用以调试或数据监测,目前面板如下:
1.Overlay UIs:所有的Overlay类型UI,点击Open和Close按钮可以模拟打开或关闭该UI。
2.Camera UIs:所有的Camera类型UI,点击Open和Close按钮可以模拟打开或关闭该UI。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。