Unity 从零开始搭建一套简单易用的UGUI小框架 扩展与优化篇(完结)

news2024/12/28 3:04:41

一个通用的UGUI小框架就算是写完了,下面是一步步的思考与优化过程

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

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

从使用者的角度来整理一下可能会发出的疑问

0. PanelManager.Instance.LoadPanel<TestPanel>("AnyWnd");

其中TestPanel和AnyWnd都代表了什么?

AnyWnd:面板预制体

TestPanel:面板预制体的脚本

我特意将二者分开就是让你理清思路,知道加载的是什么东西

其实二者可以合二为一,只需要让脚本名和预制体名一致,再修改LoadPanel中传入的名字即可

1.面板管理类的单例是如何创建的面板?

是通过对面板基类的封装,直接F12一步一步地向上阅读即可明白

2.为什么首次调用要清空面板字典?可不可以不清除?

防止重复添加,确保数据一致,避免内存泄漏

可以不清除,关键是要确保字典中的数据始终是有效且一致

3.是不是还可以继续优化?

是的,比如采用异步加载的方式?

比如通过代码设置面板的层级?

比如在面板子类中对UI的显示隐藏的动画修改?

因为我将面板基类写成了虚函数,所以你可以对其在子类中修改加载打开和关闭

甚至直接修改面板基类也没什么不可能的

面板管理类 

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UIElements;

public class PanelManager:MonoBehaviour
{
    private Transform canvasPos;//场景中的Canvas位置
    /// <summary>
    /// string =子类面板名
    /// BasePanel 里氏替换原则,所有继承了面板基类的子类面板都可以用父类容器装
    /// </summary>
    private Dictionary<string, BasePanel> panels;//存储所有面板子类的字典

    //单例
    private static PanelManager instance;
    public static PanelManager Instance => instance;
    private void Awake() {
      
        if(instance == null) {
         instance = this;
        DontDestroyOnLoad(gameObject);
        }
        else{
            Destroy(gameObject);
        }
        //初始化字典
        panels = new Dictionary<string, BasePanel>();
        panels.Clear();

        canvasPos = GameObject.Find("Canvas").transform;//虽然有性能消耗但是只用一次所以可以接受
}
    
    /// <summary>
    /// 加载面板
    /// </summary>
    /// <typeparam name="T">需要加载的子类面板脚本</typeparam>
    /// <param name="panelName">需要加载的面板名称</param>
    public void LoadPanel<T>(string panelName) where T:BasePanel,new ()
        { 
        T panel = new T();//实例化面板子类 

        if(canvasPos!=null)
        panel.CreatWnd(panelName, canvasPos);
        else
            Debug.Log("没有找到Canvas");

        panels.Add(panelName, panel);
        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}****,请检查预制体路径或者查看是否有该预制体");  
    }
}

面板基类 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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);
        if( wnd!=null){
        GameObject temp =GameObject.Instantiate(wnd); 
        temp.transform.SetParent(canvas,false);

        //将该窗口的位置记录下来,以便打开和关闭
        TempTrans = temp.transform;
        CloseWnd(); //首次实例化不要直接打开
        }   
        else{
            Debug.Log("没有正确加载到面板");
        }
    }
    //打开窗口
    public virtual void OpenWnd()
        {
        TempTrans.gameObject.SetActive(true);
    }
    //关闭窗口
    public virtual void CloseWnd() {
        TempTrans.gameObject.SetActive(false);
    }
    public abstract void Init();
}

面板子类示例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestPanel : BasePanel {
    //在这里可以写TestWnd自己的逻辑
    public override void Init() {
        Debug.Log("子类可以在此进行自己的逻辑撰写");
    }
}

 使用示例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Ctrl : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        PanelManager.Instance.LoadPanel<TestPanel>("AnyWnd");
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.O))
            {
        
            PanelManager.Instance.OpenPanel("AnyWnd");
        }
        if (Input.GetKeyDown(KeyCode.P)) {
            PanelManager.Instance.ClosePanel("AnyWnd");
        }
    }
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2211305.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【微服务】springboot远程docker进行debug调试使用详解

目录 一、前言 二、线上问题常用解决方案 2.1 微服务线上运行中常见的问题 2.2 微服务线上问题解决方案 2.3 远程debug概述 2.3.1 远程debug原理 2.3.2 远程debug优势 三、实验环境准备 3.1 搭建springboot工程 3.1.1 工程结构 3.1.2 引入基础依赖 3.1.3 添加配置文…

YOLO11改进 | 注意力机制| 对小目标友好的BiFormer【CVPR2023】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 本文介绍了一种新颖的动态稀疏注意力机制…

C++,STL 029(24.10.13)

内容 一道练习题。 &#xff08;涉及string&#xff0c;vector&#xff0c;deque&#xff0c;sort&#xff09; 题目&#xff08;大致&#xff09; 有五名选手ABCDE&#xff0c;10个评委分别对每一个选手打分&#xff0c;去除最高分和最低分&#xff0c;取平均分。 思路&…

bat脚本banenr

飞出个未来班得 echo off echo .-. echo ( ) echo - echo J L echo ^| ^| echo J L echo ^| ^| echo J L echo …

Node.js概述

1. Node.js简介 Node.js是一个基于Chrome V8引擎的JavaScript运行环境。 地址&#xff1a;Node.js 中文网 1.1 Node.js中的JavaScript运行环境 &#xff08;1&#xff09;浏览器是JavaScript的前端运行环境 &#xff08;2&#xff09;Node.js是JavaScript的后端运行环境 …

vue3之插件

插件plugins是一种能为vue添加全局功能的代码,官网连接&#xff1a;https://cn.vuejs.org/guide/reusability/plugins.html 项目的src文件夹下新建plugins文件夹 新建i18n.js文件 插件是一个拥有install方法的对象 export default {install: (app, options)>{app.config.…

Linux中用java命令运行class文件提示“错误:找不到或无法加载主类”

1.问题&#xff1a; 很多时候&#xff0c;我们需要在Linux终端编译并运行普通Java程序&#xff0c;但是会遇到以下问题&#xff1a; 错误&#xff1a;找不到或无法加载主类” 2.问题原因及解决办法 其实原因很简单&#xff0c;可能由两方面造成。 原因一 java在运行.class文…

进制的介绍

一、进制介绍 对于整数&#xff0c;有四种表示方式&#xff1a;二进制&#xff1a;0,1 &#xff0c;满 2 进 1.以 0b 或 0B 开头。十进制&#xff1a;0-9 &#xff0c;满 10 进 1。八进制&#xff1a;0-7 &#xff0c;满 8 进 1. 以数字 0 开头表示。十六进制&#xff1a;0-9 …

损失函数篇 | YOLOv8更换损失函数之SlideLoss | 解决简单样本和困难样本之间的不平衡问题

前言:Hello大家好,我是小哥谈。SlideLoss是一种新颖的损失函数,可以有效地解决YOLO算法在处理小目标和密集目标时的问题。本文所做出的改进是在YOLOv8算法中引入SlideLoss损失函数。🌈 目录 🚀1.基础概念 🚀2.更换方法 🍀🍀步骤1:loss.py文件修改 🍀�…

C#源码安装ZedGraph曲线显示组件

在软件开发里,数据的显示,已经是软件开发的大头。 如果让数据更加漂亮地、智能地显示,就是软件的核心价值了。 因为不管数据千万条,关键在于用户看到图。因为一个图表,就可以表示整个数据的趋势, 或者整个数据的走向,数据频度和密码。所以图表显示是软件的核心功能,比如…

25.1 降低采集资源消耗的收益和无用监控指标的判定依据

本节重点介绍 : 降低采集资源消耗的收益哪些是无用指标&#xff0c;什么判定依据 通过 grafana的 mysql 表获取所有的 查询表达式expr通过 获取所有的prometheus rule文件获取所有的 告警表达式expr通过 获取所有的prometheus 采集器接口 获取所有的采集metrics计算可得到现在…

SpringBoot——静态资源访问的四种方式

1.默认的静态资源目录 /static /public /resources /META-INF/resources 动态资源目录&#xff1a;/templates 2.resources静态资源目录图片存放 3. 静态资源访问 3.1.通过路径访问静态资源 http://localhost:8080/a.jpg http://localhost:8080/b.jpg …

《深度学习》OpenCV 物体跟踪 原理及案例解析

目录 一、物体跟踪 1、什么是物体跟踪 2、步骤 1&#xff09;选择跟踪算法 2&#xff09;初始化跟踪器 3&#xff09;在每个视频帧上执行跟踪 4&#xff09;可选的重新初始化 3、原理 二、案例实现 1、完整代码 1&#xff09;使用方式 2&#xff09;运行结果 2、关…

用python做一个简单的画板

一&#xff0c;画板的介绍 画板&#xff08;Paint Board&#xff09;是一个提供用户绘图、涂鸦和创作的平台。现代数字画板通常是由软件程序实现的&#xff0c;具有多种功能。以下是画板的一些主要特征和功能&#xff1a; 1. 基本绘图工具 画笔和铅笔&#xff1a;用户可以选…

Java——数组的定义与使用

各位看官&#xff1a;如果您觉得这篇文章对您有帮助的话 欢迎您分享给更多人哦 感谢大家的点赞收藏评论&#xff0c;感谢您的支持&#xff01;&#xff01;&#xff01; 一&#xff1a;数组的概念以及定义,初始化 1.1&#xff1a;数组概念以及定义 数组概念&#xff1a;可以看成…

红黑树:c++实现

1. 红⿊树的概念 红⿊树是⼀棵⼆叉搜索树&#xff0c;他的每个结点增加⼀个存储位来表⽰结点的颜⾊&#xff0c;可以是红⾊或者⿊⾊。 通过对任何⼀条从根到叶⼦的路径上各个结点的颜⾊进⾏约束&#xff0c;红⿊树确保没有⼀条路径会⽐其他路 径⻓出2倍&#xff0c;因⽽是接近平…

用LaTeX写一篇帅帅的算法学习题解

前言 先来看看用 LaTeX \text{LaTeX} LaTeX 写出来的题解是啥样&#xff0c;内容是瞎写的。 前提知识与环境 默认已经掌握了 LaTeX \text{LaTeX} LaTeX 的一些用法&#xff0c;特别是公式如何写&#xff0c;如果你对这块还是很了解&#xff0c;可以先学着使用 Typora \…

DEEP TEMPORAL GRAPH CLUSTERING.md

ICLR23 推荐指数&#xff1a; #paper/⭐ 原因的话&#xff0c;可以找找前人的一篇文章(可以看&#xff0c;但是当你阅读前人文章会发现。) 动机/优点 很明确&#xff0c;时序图只需要考虑时间相近的点&#xff0c;因此开销特别小。但是邻接矩阵&#xff0c;就要考虑所有点的关…

Dockerfile最佳实践:如何创建高效的容器

在微服务和云计算时代&#xff0c;Docker就已经成为应用开发和部署不可或缺的工具。如今虽处大模型时代&#xff0c;但这些基础技术仍然是我们需要掌握的。 容器化允许开发者将应用程序及其依赖打包到一个单一的、可移植的单元中&#xff0c;确保了可预测性、可扩展性和快速部…

反射机制(Reflection)

1. 反射 Java的反射机制(reflection)是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性&#xff1b;这种动态获取信息以及动态调用对象方法的功能称为java语言的反…