一、transform.Find
刚开始做Unity的时候,只会用transform.Find来找寻子物体,但这样做除了效率相对较低以外,还有一个对开发不太友好的事情,就是如果一个物体内子物体的层级发生了变化,就必须要修改代码路径,很麻烦。
二、解决方案
最后实现使用索引器,不需要路径,只要传入控件名,以Button为例。有两种方式注册事件
(this[Name] as GUButton).AddListener(...)
(this[Name] as GUButton).button.onClick.AddListener(...)
推荐使用第一种方式,GUButton继承自BaseGUI,除了作为transform.Find的替代方案,还提供了对Button的扩展。每个UI组件都会有一个对应的BaseGUI
完整的UI框架代码在我的github上,GUIFramework
1.BaseGUI
using UnityEngine;
namespace XDEDZL.UI
{
public abstract class BaseGUI : MonoBehaviour
{
}
}
2.GUButton
这里可以自己写一些扩展功能,用起来也方便
namespace XDEDZL.UI
{
[UnityEngine.RequireComponent(typeof(UnityEngine.UI.Button))]
public class GUButton : BaseGUI
{
public UnityEngine.UI.Button button;
private void Reset()
{
button = transform.GetComponent<UnityEngine.UI.Button>();
}
public void AddListener(UnityEngine.Events.UnityAction call)
{
button.onClick.AddListener(call);
}
}
}
3.BasePanel
这里不关心面板的逻辑,只说BaseGUI的使用方式。
下面的代码只需要关注以下几个
mUIDic : 存储对应面板下的所有BaseGUI的字典
InitGUIDic() :初始化字典
BaseGUI this[string key] :索引器,替代transfrom.Find
using System.Collections.Generic;
using UnityEngine;
namespace XDEDZL.UI
{
/// <summary>
/// 面板基类
/// </summary>
public class BasePanel
{
/// <summary>
/// UI层级,层级最低的显示在底层
/// </summary>
public int Level { get; protected set; }
/// <summary>
/// 面板名
/// </summary>
public string Name { get; protected set; }
protected RectTransform rect;
private Dictionary<string, BaseGUI> mUIDic;
protected Transform transform;
protected GameObject gameObject;
/// <summary>
/// 面板初始化,只会执行一次,在Awake后start前执行
/// </summary>
public void Init(GameObject _gameObject, string name)
{
Name = name;
gameObject = _gameObject;
transform = _gameObject.transform;
InitGUIDic();
rect = transform.GetComponent<RectTransform>();
Vector3 rectSize = rect.localScale;
rect.localScale = rectSize;
Reg();
}
/// <summary>
/// 初始化UI组件
/// </summary>
public virtual void Reg()
{
}
/// <summary>
/// 界面显示
/// </summary>
public virtual void OnOpen()
{
gameObject.SetActive(true);
transform.SetAsLastSibling();
}
/// <summary>
/// 每帧运行
/// </summary>
public virtual void OnUpdate()
{
}
/// <summary>
/// 界面暂停,被遮挡
/// </summary>
public virtual void OnPause()
{
}
/// <summary>
/// 界面恢复
/// </summary>
public virtual void OnResume()
{
}
/// <summary>
/// 退出界面,界面被关闭
/// </summary>
public virtual void OnClose()
{
gameObject.SetActive(false);
}
/// <summary>
/// 初始化UI组件字典
/// </summary>
private void InitGUIDic()
{
mUIDic = new Dictionary<string, BaseGUI>();
BaseGUI[] uis = transform.GetComponentsInChildren<BaseGUI>();
for (int i = 0; i < uis.Length; i++)
{
mUIDic.Add(uis[i].name, uis[i]);
}
}
/// <summary>
/// Find UI组件的索引器
/// </summary>
public BaseGUI this[string key]
{
get
{
if (mUIDic.ContainsKey(key))
return mUIDic[key];
else
{
throw new System.Exception(this + " : 没有名为" + key + "的UI组件");
}
}
}
}
}