【Unity笔记01】基于单例模式的简单UI框架

单例模式的UIManager

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIManager 
{
    private static UIManager _instance;
    public Dictionary<string, string> pathDict;
    public Dictionary<string, GameObject> prefabDict;
    public Dictionary<string, BasePanel> panelDict;
    private Transform _uiRoot;
    //单例模式
    public static UIManager Instance
    {
        get
        {
            if( _instance == null )
            {
                _instance = new UIManager();

            }
            return _instance;
        }
    }
    private UIManager()
    {
        Init();
    }
    private void Init()
    {
        prefabDict = new Dictionary<string, GameObject>();
        panelDict = new Dictionary<string, BasePanel>();
        pathDict = new Dictionary<string, string>()
        {
            {UIConst.Menu,"Prefabs/Pop/Menu" },
            {UIConst.SettingPop,"Prefabs/Pop/SettingPop" },
            {UIConst.OtherPop,"Prefabs/Pop/OtherPop" }
        };

    }
    public Transform UIRoot
    {
        get
        {
            if( _uiRoot == null )
            {
                _uiRoot = GameObject.Find("Canvas").transform;
            }
            return _uiRoot;
        }
    }

    public BasePanel OpenPanel(string name, bool isOnly = true)
    {
        //如果要只显示一个弹窗的话
        if(isOnly)
        {
            CloseAllPops(name);
        }
        BasePanel panel = null;
        if(panelDict.TryGetValue(name, out panel))
        {
            Debug.Log("界面已经打开过" + name);
            panel.OpenPanel(name);
            return null;
        }
        string path = "";
        if( !pathDict.TryGetValue(name, out path) )
        {
            Debug.Log("路径错误"+path);
            return null;
        }
        GameObject panelPrefab = null;
        if(!panelDict.TryGetValue(name, out panel))
        {
            string realPath =path;
            panelPrefab=Resources.Load<GameObject>(realPath);
            prefabDict.Add(name, panelPrefab);
            
        }
        //open
        GameObject panelObject = GameObject.Instantiate(panelPrefab, UIRoot, false);
        Debug.Log(panelObject.name);
        panel= panelObject.GetComponent<BasePanel>();
        if( panel == null )
        {
            Debug.Log("没有脚本哦");
        }
        
        panelDict.Add(name,panel);
        panel.OpenPanel(name);
        return panel;

    }
    public bool ClosePanel(string name)
    {
        BasePanel panel= null;
        if(! panelDict.TryGetValue(name,out panel))
        {
            Debug.Log("界面未打开");
            return false;
        }
        panel.ClosePanel();
        return true;
    }
    public void CloseAllPops(string name)
    {
        foreach(var pair in panelDict)
        {
            if (pair.Key == name) continue;
            pair.Value.ClosePanel();
        }
    }
}

面板的基类

控制面板的打开和关闭,带动画

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class BasePanel : MonoBehaviour
{
    private bool isRemove = false;
    private string name;
    public virtual void OpenPanel(string name)
    {
        this.name = name;
        gameObject.SetActive(true);
        OpenAnimation(gameObject);
    }
    public virtual void ClosePanel()
    {
        isRemove = true;
        CloseAnimation(gameObject).OnComplete(() =>
        {
            gameObject.SetActive(false);

        });
        //gameObject.SetActive(false);
    }

    public void OpenAnimation(GameObject gameObject)
    {
        //用dotween 从0%放大到105% 再缩小到95% 再到100%
        //初始缩放为 0
        gameObject.transform.localScale = Vector3.zero;

        //创建动画序列
        Sequence scaleSequence = DOTween.Sequence();

        // 添加动画步骤
        scaleSequence.Append(gameObject.transform.DOScale(1.05f, 0.3f)); // 放大到 105%
        scaleSequence.Append(gameObject.transform.DOScale(0.95f, 0.3f)); // 缩小到 95%
        scaleSequence.Append(gameObject.transform.DOScale(1.0f, 0.3f));  // 回到 100%

        // 缓动
        scaleSequence.SetEase(Ease.OutBack);
    }
    public Tween CloseAnimation(GameObject gameObject)
    {
        Sequence scaleSequence = DOTween.Sequence();
        scaleSequence.Append(gameObject.transform.DOScale(0f, 0.2f));
        
        return scaleSequence;
    }
}

常量

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIConst 
{
    public const string Menu = "Menu";
    public const string SettingPop = "SettingPop";
    public const string OtherPop = "OtherPop";
}

使用

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MenuPanel : BasePanel
{
    public void OpenNest()
    {
        UIManager.Instance.OpenPanel(UIConst.OtherPop);
    }
    public void Close()
    {
        UIManager.Instance.ClosePanel(UIConst.Menu);
    }
}
相关推荐
Zhao-Jichao2 小时前
AI Prompting for Everyone 课程笔记 - P21 总结 Conclusion
人工智能·笔记
欢欢李2 小时前
【LTE L3 笔记 05】LTE同步信号
笔记·无线通信·物理层·lte·空口协议
La Pulga4 小时前
【FreeRTOS源码学习笔记】空闲任务与阻塞延时
笔记·mcu·学习·嵌入式·freertos·实时操作系统
蒸蒸yyyyzwd4 小时前
秋招学习笔记 day106
笔记·学习
小李不想当小白5 小时前
WDG看门狗(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
欢欢李6 小时前
【LTE L3 笔记 04】LTE帧结构
笔记·无线通信·物理层·lte·空口协议
SmalBox8 小时前
08-04-热更新-首包资源策略
unity3d·游戏开发
Zhao-Jichao8 小时前
AI Prompting for Everyone 课程笔记 - P20 实验与期末项目 Lab and Final Project
前端·人工智能·笔记
Z21-X9 小时前
云原生运维实战笔记:企业网站综合上云部署与云运维服务全景解析
运维·笔记·学习·云原生
tealcwu9 小时前
【Unity基础】为什么游戏需要物理按键映射?从 Unity Input Manager 到跨引擎输入设计
java·游戏·unity