至于具体怎么处理要看个人吧,我使用的枚举作为标记区分;
先上管理类:
一、UI管理类

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

public class UIManager : MonoBehaviour
{
    private static Transform canvas;
    public static Transform Canvas
    {
        get
        {
            if (canvas == null)
            {
               canvas= GameObject.FindWithTag("Canvas").transform;             
            }
            return canvas;
        }
    }
    /// <summary>
    /// 已经加载过的Panel;
    /// </summary>
    private static Dictionary<PanelNameEnum, BasePanel> m_panelDic = new Dictionary<PanelNameEnum, BasePanel>();

    public static BasePanel LoadPanel(PanelNameEnum panelEnum, PanelNameEnum prePanel)//传入显示的界面,参数自己;
    {      
        BasePanel target = null;
        string pName = Enum.GetName(typeof(PanelNameEnum), panelEnum);
        if (!m_panelDic.TryGetValue(panelEnum,out target))
        {
        	//通过名字uiprefabs(自己定义的)加载AB包,以及AB包的资源(想要加载的Panel);
            GameObject t= ABManager.Instance.LoadAssets<GameObject>("uiprefabs", pName);
            GameObject temp = Instantiate(t, Canvas, false);
            temp.name = pName;
            target= temp.GetComponent<BasePanel>();
            m_panelDic.Add(panelEnum, target);            
        };
        //根据他的枚举类型,决定当前的这个之前的panel是否需要隐藏;
        if(prePanel!=PanelNameEnum.None)
             SwitchEnumPanel(target.ScreenEnu, m_panelDic[prePanel]);
        target.gameObject.SetActive(true);
        target.transform.SetParent(Canvas,false);
        target.transform.SetAsLastSibling();
        return target;
    }
    //Loading 专用加载;传数据或者传递方法以后在补充;
    public static BasePanel LoadPanel(string title=null,string content=null,string imageName=null)
    {
        BasePanel target=null;
        string pName = Enum.GetName(typeof(PanelNameEnum), PanelNameEnum.LoadingPanel);
        if (!m_panelDic.TryGetValue(PanelNameEnum.LoadingPanel, out target))
        {
            GameObject t = ABManager.Instance.LoadAssets<GameObject>("uiprefabs", pName);
            GameObject temp = Instantiate(t, Canvas, false);
            temp.name = pName;
            target = temp.GetComponent<BasePanel>();
            m_panelDic.Add(PanelNameEnum.LoadingPanel, target);
        };
        target.gameObject.SetActive(true);
        target.transform.SetParent(Canvas, false);
        target.transform.SetAsLastSibling();
        if(target is LoadingPanel)
        {
            (target as LoadingPanel).ShowContent(title, content, imageName);
        }
        return target;
    }

    //参数panel是即将要打开的。
    private static void SwitchEnumPanel(PanelScreenEnum panel,BasePanel panelName)
    {      
        switch (panel)
        {
            case PanelScreenEnum.FullScreen:
                panelName.ISShow(false);
                break;
            case PanelScreenEnum.HalfScreen:
                panelName.ISShow(true);
                break;
            case PanelScreenEnum.Tips:
                panelName.ISShow(true);
                break;
           
            default:
                break;
        }

    }
    public static void DestoryPanel(PanelNameEnum panelEnum)
    {
        if (m_panelDic.ContainsKey(panelEnum))
        {
            BasePanel temp = m_panelDic[panelEnum];
            m_panelDic.Remove(panelEnum);
            Destroy(temp.gameObject);
        }
        else
        {
            MDebug.LogError($"Please Check {panelEnum},Don't Destory!!!");
        }
    }
    public static void HideTargetPanel(PanelNameEnum panelEnum)
    {
        BasePanel target = null;
        if (m_panelDic.TryGetValue(panelEnum, out target))
        {
            target.ISShow(false);
        }
    }
    public static void HideAllPanel()
    {
        if (m_panelDic == null)
        {
            MDebug.LogError("panelDic is null, please Check!!!");
        }
        foreach (var item in m_panelDic.Values)
        {
            item.ISShow(false);
        }
    }

    /// <summary>
    /// 谨慎使用;
    /// </summary>
    public static void ClearPanelDic()
    {
        foreach (var item in m_panelDic.Values)
        {
            Destroy(item.obj);
        }
        m_panelDic.Clear();
        GC.Collect();
    }
}

二、UI的基类

public abstract class BasePanel : MonoBehaviour
{
	//表示该UIPanel是全屏的还是其他的;
    protected PanelScreenEnum screenEnu = PanelScreenEnum.HalfScreen;
    //名字的枚举实际上就是要么通过名字字符串直接加载,要么就是通过枚举加载,这个加载的方式是和UIManager自己定义的有关的,怎么写都行;只是我用的枚举而已。
    protected PanelNameEnum nameEnum;
    public void Awake()
    {
   		//数据初始化,不一定用得到;       
        InitData();
    }
    public void OnUpdate()
    {
    	//刷新UI的逻辑;
        UpdateUI();
    }
    public GameObject obj
    {
        get
        {
            return gameObject;
        }       
    }

    public PanelScreenEnum ScreenEnu
    {
        get => screenEnu;
    }
    public PanelNameEnum NameEnum { get => nameEnum; }

    public void ISShow(bool isShow)
    {

        obj.SetActive(isShow);
    }
    protected virtual void UpdateUI() { }
    protected abstract void InitData();
}

三、单独把Loading界面拿出来

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

public class LoadingPanel : BasePanel
{
    [SerializeField]
    private Image m_Bg;
    public Slider m_Slider;
    public Text  m_title_text;
    public Text m_Content;
    public Text showSliderValue_text;
    protected override void InitData()
    {
        this.screenEnu = PanelScreenEnum.FullScreen;
        this.nameEnum = PanelNameEnum.LoadingPanel;
        MessageManager.AddListener("loading", DoValueSlider);
    }
    public void OnDestroy()
    {
        MessageManager.RemoveFunc("loaidng");
    }
    public void DoValueSlider(float num)
    {
        m_Slider.value = num;
        MDebug.Log("Loading界面的进度值 m_Slider.value:" + m_Slider.value);
        if (num >= 0.8999)
        {
            m_Slider.value = 1;
        }
        showSliderValue_text.text = (m_Slider.value * 100).ToString() + "%";
    }
    public void ShowContent(string title = null, string content = null, string imageName = null)
    {
        if (title != null && content != null)
            m_title_text.text = title;
        m_Content.text = content;
        if (imageName != null && imageName!=string.Empty)
        {
            MDebug.Log(imageName != string.Empty);
            MDebug.Log(imageName!=null);
            m_Bg = ABManager.Instance.LoadAssets<Image>("iamgebg", imageName);
        }
    }
}

注意: MessageManager.AddListener(“loading”, DoValueSlider);在界面一打开的时候我就把这个消息注册到消息盒子里面去了,在那执行的呢?还记得场景管理类中吗?进入每个场景,就首先通过UIManager加载了loading界面,因此也就把这个委托注册到MessageManager这个雷中秋u了。然后,通过MySceneManager执行了LoadSceneMsg管理类中的异步加载场景的方法,在这个方法里面, 执行了MessageManager.DoFunc(“loading”, async.progress);通过传入两个参数,执行了之前注册的委托DoValueSlider。当加载完成以后,我又重新移除了这个方法。如果销毁这个界面,那么就自动移除了这个方法。
while (async.progress < 0.9f)
{
MDebug.Log(“async.progress” + async.progress);
MessageManager.DoFunc(“loading”, async.progress);
yield return null;
}

到此为止,框架算是完成了。因为有部分东西其实还是不合理,但是我实在是懒得改了……自行解决就行了。

下面这个是关于音乐相关处理:
四、其他播放音乐的管理。同样的特效也是这个道理,没什么好说的。

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

public class MusicManager :AutoSingleton<MusicManager>
{
    private AudioClip buttonClip;
    private AudioClip bgClip;
    private AudioClip otherClip;
    private GameObject audioSource;
    private AudioSource buttonAudioSource;
    private AudioSource bgAudioSource;
    private AudioSource otherAudioSource;

    private void Awake()
    {
        CreatAudioSource();
        PlayBGAudio(true);
    }
    private void CreatAudioSource()
    {
        if (audioSource == null)
        {
            audioSource = new GameObject("AudioSourceComponent");
            DontDestroyOnLoad(audioSource);
            MDebug.Log("创建了物体AudioSource");
        }
        if (buttonAudioSource == null)
        {
            GameObject go = new GameObject("buttonAudioSource");
            go.transform.SetParent(audioSource.transform);
            buttonAudioSource = go.AddComponent<AudioSource>();
        }
        if (bgAudioSource == null)
        {
            GameObject go = new GameObject("bgAudioSource");
            bgAudioSource = go.AddComponent<AudioSource>();
            go.transform.SetParent(audioSource.transform);
        }
        if (otherAudioSource == null)
        {
            GameObject go = new GameObject("otherAudioSource");
            otherAudioSource = go.AddComponent<AudioSource>();
            go.transform.SetParent(audioSource.transform);
        }
    }
    public void OnMyClickClip()
    {
        if (buttonClip == null)
            buttonClip = ABManager.Instance.LoadAssets<AudioClip>("audio", "buttonClip");
        buttonAudioSource.clip = buttonClip;
        buttonAudioSource.mute = false;
        buttonAudioSource.loop = false;
        buttonAudioSource.Play();
    }
    public void PlayBGAudio(bool isPlay)
    {
        if (bgClip == null)
        {
            bgClip = ABManager.Instance.LoadAssets<AudioClip>("audio", "zanyong_bg");
        }
        bgAudioSource.clip = bgClip;
        buttonAudioSource.mute = false;
        buttonAudioSource.loop = true;
        bgAudioSource.Play();
    }
}

搞定!!!以后有空可能会写一点关于Shader的东西吧,也可能会写一些关于Ai相关的FSM啊,GOAP之类的,自动寻路之类的。我要说但是了,实在时间不太多(懒的另一种说法),基本除了在学习就是学习(这个是真的),其余时间睡觉了。我属于死宅那种……
我到现在游戏开发工作满打满算才两年,实际上也是个新手,说是啥也不会也不为过。最开始走了不少弯路,最近半年对shader比较感兴趣,所以不务正业玩了很久的shader,我对写代码感兴趣,所以不爱玩连连看,连连看也就了解的比较少吧。这个工程呢,下面我贴出来就行了,本来想自己写个demo玩的,但是美术资源不好找,最近又有新的学习目标,就搁浅了。过段时间和约好的三个大佬(一个地编,一个特效,一个前端主程),正在忽悠一个原画小哥,打算抽空忽悠一个模型过来,人凑齐了可能会一起做个小游戏玩吧。