Unity 从零开始搭建一套简单易用的UGUI小框架 基础分析篇-CSDN博客
开始撰写
从基础分析篇我们得到了三个类,面板基类,管理类和面板子类
那就从面板基类开始,定义其基本行为
面板基类
基本方法都很简单,分别是首次加载并打开面板,关闭和重新打开
加载我就采用unity的资源加载Resources方法
但是需要考虑几个问题
0.需要一个面板预制体并放到对应路径下
我就将其放到Wnd下起名叫AnyWnd了
1.因为unity特性,面板加载出来需要放在Canvas下才会被显示
所以需要设置父物体为Canvas
2.放在Canvas下还需要设置位置
所以需要记录一下传入的面板的原来的位置
然后就可以写代码了
public abstract class BasePanel {
protected Transform tempTrans;//记录要打开窗口的位置
//实例化窗口
public void CreatWnd(string wndName,Transform canvas)
{
//加载
GameObject wnd = Resources.Load<GameObject>("Wnd/"+wndName);
GameObject temp =GameObject.Instantiate(wnd);
temp.transform.SetParent(canvas,false);
//将该窗口的位置记录下来,以便打开和关闭
tempTrans = temp.transform;
}
}
重新打开和关闭面板如下
//打开窗口
public void OpenWnd()
{
tempTrans.gameObject.SetActive(true);
}
//关闭窗口
public void CloseWnd() {
tempTrans.gameObject.SetActive(false);
}
是不是非常简单!!!
面板子类
就是随便一个面板子类都可以继承基类,从而有基类的方法,这个我就不多说了
public class TestPanel:BasePanel
{
//在这里可以写TestWnd自己的逻辑
}
面板管理类
因为面板基类的Creat方法要传入两个参数
所以我们就需,被实例化的面板的名字和场景中Canvas的transform
public class PanelManager:MonoBehaviour
{
public Transform canvesPos;
public TestPanel testWnd;
private void Start() {
testWnd = new TestPanel();
testWnd.CreatWnd("AnyWnd", canvesPos);
}
private void Update() {
if(Input.GetKeyDown(KeyCode.W))
{
testWnd.OpenWnd();
}
if(Input.GetKeyDown(KeyCode.S))
{
testWnd.CloseWnd();
}
}
}
运行试一下效果
这样,我就让AnyWnd这个面板在没有挂载脚本的情况下
面板管理类可以控制所有面板
且,每一个子类对象都能控制其对应的实际面板
优化
面板基类
用作记录要打开窗口的位置的临时Transform
可以成一个属性,使得外部只能调用,不能修改
protected Transform TempTrans { //记录要打开窗口的位置
get;
private set;
}
先前的方法全部可以写成虚方法,另外添加一个抽象类Init方法,以便拓展子类的功能
public abstract class BasePanel {
protected Transform TempTrans { //记录要打开窗口的位置
get;
private set;
}
//实例化窗口
public virtual void CreatWnd(string wndName,Transform canvas)
{
//加载
GameObject wnd = Resources.Load<GameObject>("Wnd/"+wndName);
GameObject temp =GameObject.Instantiate(wnd);
temp.transform.SetParent(canvas,false);
//将该窗口的位置记录下来,以便打开和关闭
TempTrans = temp.transform;
//首次实例化不要直接打开
CloseWnd();
}
//打开窗口
public virtual void OpenWnd()
{
TempTrans.gameObject.SetActive(true);
}
//关闭窗口
public virtual void CloseWnd() {
TempTrans.gameObject.SetActive(false);
}
public abstract void Init();
}
面板管理类
面板管理类写具体控制逻辑(比如input.getkeydown......)就不太正确
一般都是外部的什么东西去调用面板管理类封装好的方法,如下图
况且,面板管理类突出一个管理功能,那我就将其功能贯彻到底
0.设置成单例模式
private static PanelManager instance;
public static PanelManager Instance=>instance;
private void Awake() {
if(instance == null) {
instance = this;
DontDestroyOnLoad(gameObject);
}
else{
Destroy(gameObject);
}
}
1.对其两个参数进行优化,使其自动得到Canvas和需要管理的子类
2.如果面板很多的情况下,可以添加一个字典进行管理
private Transform canvesPos;//场景中的Canvas位置
/// <summary>
/// string =子类面板名
/// BasePanel 里氏替换原则,所有继承了面板基类的子类面板都可以用父类容器装
/// </summary>
private Dictionary<string, BasePanel> panles;//存储所有面板子类的字典
//单例
private static PanelManager instance;
public static PanelManager Instance=>instance;
private void Awake() {
if(instance == null) {
instance = this;
DontDestroyOnLoad(gameObject);
}
else{
Destroy(gameObject);
}
//初始化字典
panles = new Dictionary<string, BasePanel>();
panels.Clear();
canvesPos = GameObject.Find("Canvas").transform;//虽然有性能消耗但是只用一次所以可以接受
}
3.对面板基类进行再封装,让其他模块用到的时候直接调用
/// <summary>
/// 加载面板
/// </summary>
/// <typeparam name="T">需要加载的子类面板脚本</typeparam>
/// <param name="panelName">需要加载的面板名称</param>
public void LoadPanel<T>(string panelName) where T:BasePanel,new ()
{
T panel = new T();//实例化面板子类
panels.Add(panelName, panel);
panel.CreatWnd(panelName, canvesPos);
panel.Init();//子类重写的抽象方法,用于执行自己的逻辑
}
public void OpenPanel(string panelName)
{
if (panels.TryGetValue(panelName, out BasePanel curPanel)){
curPanel.OpenWnd(); }
else
Debug.Log($"没有找到正确的面板****{panelName}****,请检查预制体路径或者查看是否有该预制体");
}
public void ClosePanel(string panelName) {
if (panels.TryGetValue(panelName, out BasePanel panel)) {
panel.CloseWnd(); }
else
Debug.Log($"没有找到正确的面板****{panelName}****,请检查预制体路径或者查看是否有该预制体");
}
好了,这就是全部内容了,关于所有代码和扩展性请看下一篇:扩展与总结篇