基于ET框架和UGUI的简单UI框架实现(转)
前言
此框架对应Et2.0版本,目前已过时!请跳转到最新的et3.3版本:http://www.tinkingli.com/?p=270
本框架是在ET框架上进行修改的,使用的是Unity自带的UGUI。
其实ET本身就带有简单的UI框架,建议学习之前先看懂ET里面的UI组件,主要看UIComponent,IUIFactory,UI及与其相关的类,明白ET中整个UI的运作流程。
其实ET中UI组件一般来说也是够用了,不过我是由原本项目移植到ET框架,我打算部分沿用原框架中的UI架构,再结合ET中的UI组件,就衍生出了这篇文章,一个“基于ET框架和UGUI的简单UI框架”。
框架介绍
本框架特点:
1、层级分明,本框架把UI分成5层,层级依次递增,在Unity面板设置好属性后自动加载到该层
2、关闭界面不直接销毁UI物体,而是调用Close方法,并把界面移到UIHiden层进行隐藏,等待下次Show调用,这样可以避免重复加载和实例化UI物体,当你部分UI界面可能出现多次关闭和打开操作时,能减轻运行压力
3、只需进行一次获取引用操作,一般我们会在Awake中通过ReferenceCollector获取需要引用到的物体(例如:返回按钮,输入文本框等),而Show中负责展示界面逻辑(文本框内容初始化,弹出动画等),因为Awake只会调用一次,而Show则每次打开都会调用,所以能减少GetComponent,以及从ReferenceCollector中取出物体的调用,节省性能的开销
4、拓展方便,假如想要拓展什么想要的功能,大部分都可直接在UIBaseComponent中直接修改即可(下面实例拓展了两个我用到的事件OnCloseOneTime和OnClose,大家用不到可直接去掉)
5、当然也可以手动调用UIComponent.Remove()方法进行真正的移除UI操作(直接销毁物体),有需要的也可以自行实现一个定时卸载操作,就是关闭(Close)一定时间后没有再打开(Show)的UI实行移除(Remove),节约内存
本框架主要是先把所有UI分成5层:
不同层根据名字有不同作用,UIHiden比较特殊,而另外的4层根据名称意思,层级逐层递增
UIHiden:隐藏层,当调用Close的时候,实际上是把UI物体移到该层中进行隐藏
Bottom:底层,一般用来放置最底层的UI
Medium:中间层,比较常用,大部分界面均是放在此层
Top:上层,一般是用来放各种弹窗,小窗口之类的
TopMost:最上层,一般用来做各种遮罩层,屏蔽输入,或者切换动画等
Unity工程中的修改
1.在Model命名空间下添加WindowLayer枚举
namespace Model
{
//窗体的层级类型
public enum WindowLayer
{
UIHiden = 0,
Bottom = 1,
Medium = 2,
Top = 3,
TopMost = 4,
}
}
2.修改CanvasConfig类,添加UiWindowLayer字段,该字段表明此UI属于哪一层。
public class CanvasConfig: MonoBehaviour
{
public string CanvasName;
public WindowLayer UiWindowLayer = WindowLayer.Medium;
}
然后直接可以在Unity面板中修改层级

UIComponent中的修改(Hotfix工程)
1.添加两个方法,初始化UI层级和修改UI层级
//初始化UI层级
private void InstantiateUi(Transform parent)
{
WindowLayer[] _names = new WindowLayer[] {
WindowLayer.UIHiden,
WindowLayer.Bottom,
WindowLayer.Medium,
WindowLayer.Top,
WindowLayer.TopMost
};
Camera _cam = new GameObject().AddComponent<Camera>();
_cam.clearFlags = CameraClearFlags.Depth;
_cam.cullingMask = 1 << LayerMask.NameToLayer("UI");
_cam.orthographic = true;
_cam.depth = 10;
_cam.name = "UiCamera";
_cam.transform.SetParent(parent);
_cam.transform.localPosition = Vector3.zero;
foreach (var layer in _names)
{
var it = layer.ToString();
GameObject _go = new GameObject();
this.m_allLayers.Add(layer, _go);
Canvas _canvas = _go.AddComponent<Canvas>();
_canvas.renderMode = RenderMode.ScreenSpaceCamera;
_canvas.worldCamera = _cam;
_canvas.sortingOrder = (int)layer;
CanvasScaler _scale = _go.AddComponent<CanvasScaler>();
_scale.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
_scale.referenceResolution = new Vector2(1920, 1080);
_scale.matchWidthOrHeight = 1;
GraphicRaycaster _graphic = _go.AddComponent<GraphicRaycaster>();
_go.name = it;
_go.transform.SetParent(parent);
_go.transform.localPosition = Vector3.zero;
if (layer == WindowLayer.UIHiden)
{
_go.layer = LayerMask.NameToLayer("UIHiden");
_graphic.enabled = false;
}
else
{
_go.layer = LayerMask.NameToLayer("UI");
}
}
}
//修改UI层级
private void SetViewParent(UI ui, WindowLayer layer)
{
RectTransform _rt = ui.GameObject.GetComponent<RectTransform>();
_rt.SetParent(m_allLayers[layer].transform);
_rt.anchorMin = Vector2.zero;
_rt.anchorMax = Vector2.one;
_rt.offsetMax = Vector2.zero;
_rt.offsetMin = Vector2.zero;
_rt.pivot = new Vector2(0.5f, 0.5f)