前言
在UI模块初探里发现了小问题,按钮点击没有反应和每个界面都添加了Canvas,所以准备调整一下。
1.调整优化UI模块
按钮点击没有反应可能的原因在初章已经说过了,这里把每个挂载到界面的Canvas组件移除掉,然后在UIComponent的Start函数m_InstanceRoot实例化根Canvas组件,具体代码如下:
if (m_InstanceRoot == null) //默认根层级
{
m_InstanceRoot = new GameObject("UI Root");
m_InstanceRoot.transform.SetParent(transform);
m_InstanceRoot.transform.localScale = Vector3.one;
m_InstanceRoot.AddComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay;
m_InstanceRoot.AddComponent<GraphicRaycaster>();
CanvasScaler tmpCanvasScaler = m_InstanceRoot.AddComponent<CanvasScaler>();
tmpCanvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
tmpCanvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
tmpCanvasScaler.referenceResolution = new Vector2(Screen.width,Screen.height);
tmpCanvasScaler.matchWidthOrHeight = 1;
}
先把界面Canvas删掉以后,在UGuiForm.cs的OnDepthChanged函数会报错误,所以这里修改一下函数的实现,如图所示:
主要是这些地方要修改一下,这个接口功能自己百度啦,Unity渲染顺序是越深度越下端越往后去渲染出来,所以界面要被遮挡,就将0传递进去就表示这个层级下它移动到最上层,这样后面层级的界面的就会把它遮挡住了。到这里基本就修复完成,接下来深度的了解一下UI模块设计巧妙之处。
2.优秀的UI模块
系统的看过UI框架之后,明显感觉UI模块写的功能详细和可编辑可拓展,之前也写过基于Unity的小框架,只不过很多地方都在代码中定死。看过UIComponent这个脚本之后,就感觉UI框架会很不错,很多可控的参数,可以调整需要实例化多少个界面组,之前写的代码如下(可以和GF写的UI模块进行对比):
private void InitGame()
{
GameObject UIRoot = new GameObject("UIRoot");
GameObject uiCamera = new GameObject("uiCamera");
GameObject NormalRoot = new GameObject(TagInfos.NormalRoot);
GameObject PopupRoot = new GameObject(TagInfos.PopupRoot);
GameObject HintRoot = new GameObject(TagInfos.HintRoot);
GameObject ToppestRoot = new GameObject(TagInfos.ToppestRoot);
GameObject EffectRoot = new GameObject(TagInfos.EffectRoot);
uiCamera.transform.SetParent(UIRoot.transform);
NormalRoot.transform.SetParent(UIRoot.transform);
PopupRoot.transform.SetParent(UIRoot.transform);
HintRoot.transform.SetParent(UIRoot.transform);
ToppestRoot.transform.SetParent(UIRoot.transform);
EffectRoot.transform.SetParent(UIRoot.transform);
UIRoot.layer = 5;
uiCamera.layer = 5;
NormalRoot.layer = 5;
PopupRoot.layer = 5;
HintRoot.layer = 5;
ToppestRoot.layer = 5;
EffectRoot.layer = 5;
//初始化画布组件
Camera camera = uiCamera.AddComponent<Camera>();
Canvas canvas = UIRoot.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceCamera;
canvas.worldCamera = camera;
canvas.pixelPerfect = true;
canvas.planeDistance = 100;
canvas.sortingOrder = -1;
CanvasScaler canvasScaler = UIRoot.AddComponent<CanvasScaler>();
canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
canvasScaler.referenceResolution = new Vector2(1980, 1080);
canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
canvasScaler.matchWidthOrHeight = 1;
canvasScaler.referencePixelsPerUnit = 100;
UIRoot.AddComponent<GraphicRaycaster>();
//初始化相机组件
camera.clearFlags = CameraClearFlags.Depth;
camera.cullingMask = 1 << 5;//表示UI
camera.orthographic = true;
camera.orthographicSize = 5;
camera.nearClipPlane = -10;
camera.farClipPlane = 50;
camera.depth = 10;
uiCamera.AddComponent<AudioListener>();
//正常层级
canvas = NormalRoot.AddComponent<Canvas>();
RectTransform rectTransform = canvas.transform as RectTransform;
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.offsetMax = Vector2.zero;
rectTransform.offsetMin = Vector2.zero;
canvas.overrideSorting = true;
canvas.pixelPerfect = true;
canvas.sortingOrder = 0;
NormalRoot.AddComponent<GraphicRaycaster>();
//弹窗口层级
canvas = PopupRoot.AddComponent<Canvas>();
rectTransform = canvas.transform as RectTransform;
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.offsetMax = Vector2.zero;
rectTransform.offsetMin = Vector2.zero;
canvas.overrideSorting = true;
canvas.pixelPerfect = true;
canvas.sortingOrder = 100;
PopupRoot.AddComponent<GraphicRaycaster>();
//提示层级
canvas = HintRoot.AddComponent<Canvas>();
rectTransform = canvas.transform as RectTransform;
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.offsetMax = Vector2.zero;
rectTransform.offsetMin = Vector2.zero;
canvas.overrideSorting = true;
canvas.pixelPerfect = true;
canvas.sortingOrder = 200;
HintRoot.AddComponent<GraphicRaycaster>();
//最高层级
canvas = ToppestRoot.AddComponent<Canvas>();
rectTransform = canvas.transform as RectTransform;
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.offsetMax = Vector2.zero;
rectTransform.offsetMin = Vector2.zero;
canvas.overrideSorting = true;
canvas.pixelPerfect = true;
canvas.sortingOrder = 300;
ToppestRoot.AddComponent<GraphicRaycaster>();
//2D特效层级
canvas = EffectRoot.AddComponent<Canvas>();
rectTransform = canvas.transform as RectTransform;
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.offsetMax = Vector2.zero;
rectTransform.offsetMin = Vector2.zero;
canvas.overrideSorting = true;
canvas.pixelPerfect = true;
canvas.sortingOrder = 400;
EffectRoot.AddComponent<GraphicRaycaster>();
DontDestroyOnLoad(UIRoot);
DontDestroyOnLoad(this);
}
优秀的框架应该暴露给使用者更多的可编辑可能性,而且GF框架还是写的很细腻,界面会挂载2个脚本(UIForm.cs和UGuiForm.cs),第一个感觉就是没有必要分开,将它们可以合起来的。但是思考之后,想清楚了UIForm是框架用来控制的(业务逻辑方面的),UGuiForm主要是用来UI逻辑方面的控制,更好的高内聚低耦合。