Unity 从零开始搭建一套简单易用的UGUI小框架 功能撰写与优化篇

Unity 从零开始搭建一套简单易用的UGUI小框架 基础分析篇-CSDN博客

开始撰写

从基础分析篇我们得到了三个类,面板基类,管理类和面板子类

那就从面板基类开始,定义其基本行为

面板基类

基本方法都很简单,分别是首次加载并打开面板,关闭和重新打开

加载我就采用unity的资源加载Resources方法

Unity数据持久化 万物之源Resources动态资源加载_unity 动态加载资源-CSDN博客

但是需要考虑几个问题

0.需要一个面板预制体并放到对应路径下

我就将其放到Wnd下起名叫AnyWnd了

1.因为unity特性,面板加载出来需要放在Canvas下才会被显示

所以需要设置父物体为Canvas
2.放在Canvas下还需要设置位置

所以需要记录一下传入的面板的原来的位置

然后就可以写代码了

cs 复制代码
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;
    }
}

重新打开和关闭面板如下

cs 复制代码
    //打开窗口
    public void OpenWnd()
        {
        tempTrans.gameObject.SetActive(true);
    }
    //关闭窗口
    public void CloseWnd() {
        tempTrans.gameObject.SetActive(false);
    }

是不是非常简单!!!

面板子类

就是随便一个面板子类都可以继承基类,从而有基类的方法,这个我就不多说了

cs 复制代码
public class TestPanel:BasePanel
{
    //在这里可以写TestWnd自己的逻辑
}

面板管理类

因为面板基类的Creat方法要传入两个参数

所以我们就需,被实例化的面板的名字场景中Canvas的transform

cs 复制代码
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

可以成一个属性,使得外部只能调用,不能修改

C# & Unity 面向对象补全计划 之 类class-CSDN博客

cs 复制代码
  protected Transform TempTrans { //记录要打开窗口的位置
        get;
        private set;
    }

先前的方法全部可以写成虚方法,另外添加一个抽象类Init方法,以便拓展子类的功能

C# & Unity 面向对象补全计划 之 初识继承方法与多态_unity 继承函数方法-CSDN博客

cs 复制代码
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.设置成单例模式

cs 复制代码
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.如果面板很多的情况下,可以添加一个字典进行管理

cs 复制代码
    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.对面板基类进行再封装,让其他模块用到的时候直接调用

cs 复制代码
    /// <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}****,请检查预制体路径或者查看是否有该预制体");  
    }

好了,这就是全部内容了,关于所有代码和扩展性请看下一篇:扩展与总结篇

相关推荐
向宇it7 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
九鼎科技-Leo7 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
Heaphaestus,RC8 小时前
【Unity3D】获取 GameObject 的完整层级结构
unity·c#
芋芋qwq8 小时前
Unity UI射线检测 道具拖拽
ui·unity·游戏引擎
baivfhpwxf20239 小时前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
直裾9 小时前
Scala全文单词统计
开发语言·c#·scala
tealcwu9 小时前
【Unity服务】关于Unity LevelPlay的基本情况
unity·游戏引擎
ZwaterZ10 小时前
vue el-table表格点击某行触发事件&&操作栏点击和row-click冲突问题
前端·vue.js·elementui·c#·vue
大眼睛姑娘12 小时前
Unity3d场景童话梦幻卡通Q版城镇建筑植物山石3D模型游戏美术素材
unity·游戏美术
ZwaterZ12 小时前
el-table-column自动生成序号&&在序号前插入图标
前端·javascript·c#·vue