一:目标
在制作游戏过程中,UI界面都是必不可少的,多则上百个少则几个,如果这些UI界面都放在场景里(如下图所示),那么运行的时候会占用大量的内存

个别都是将每一个UI界面制作成一个Prefab动静的进行显示暗藏,加载卸载
所以咱们须要一个管理器对立治理UI的相干操作

二:解决的问题及长处

——不须要创立UI画布和UI相机,动态创建并设置属性
——治理每一个UI界面的层级
——关上和敞开UI界面
——查找某一个UI界面

三:应用办法

——将所有UI制作成预制体对立放在Resources—Prefabs—UI文件夹下
——所有的UI预制体都须要与挂载在身上的脚本名雷同
——所有的UI预制体身上的脚本都须要继承UIBase基类
——应用UIMgr.Ins.XXX

UIMgr.Ins.OpenUI<UI_Main>();UIMgr.Ins.CloseUI<UI_Main>();UIMgr.Ins.TopUI;

——依据不同我的项目需要设置UI画布的缩放:UIMgr.Ins.SetCanvasScaler()

四:代码实现

using UnityEngine;using UnityEngine.UI;using System.Collections.Generic;using UnityEngine.EventSystems; /// <summary>/// UI基类/// </summary>public class UIBase : MonoBehaviour{    /// <summary>    /// 关上UI时    /// </summary>    public virtual void OnView()    {        transform.SetAsLastSibling();        gameObject.SetActive(true);    }     /// <summary>    /// 敞开UI时    /// </summary>    public virtual void OnDisView()    {        gameObject.SetActive(false);    }} /// <summary>/// UI管理器/// </summary>public class UIMgr : Singleton<UIMgr>{    public const string UIDir = "Prefabs/UI/";//UI目录     //渲染UI的画布    private Canvas uiCanvas;    public Canvas UICanvas { get { return uiCanvas; } }     //渲染UI的相机    private Camera uiCamera;    public Camera UICamera { get { return uiCamera; } }     //显示在最顶部的UI    private UIBase topUI;    public UIBase TopUI { get { return topUI; } }     private Dictionary<string, UIBase> uiDict = new Dictionary<string, UIBase>();//场景中的UI     protected override void Init()    {        base.Init();         if (uiCamera == null)        {            uiCamera = CreateUICamera();        }        if (uiCanvas == null)        {            uiCanvas = CreateUICanvas();        }         //设置Canvas缩放        SetCanvasScaler(new Vector2(750, 1334), false);    }     /// <summary>    /// 关上UI    /// </summary>    public T OpenUI<T>(string uiRoot = "")        where T : UIBase    {        string uiName = typeof(T).Name;        if (!uiDict.ContainsKey(uiName))        {            CreateUI(uiName, uiRoot);        }         UIBase ui = uiDict[uiName];        ui.OnView();        FindTopUI();         return ui as T;    }     /// <summary>    /// 敞开UI    /// </summary>    public void CloseUI(string uiName, bool destroy = false)    {        if (!uiDict.ContainsKey(uiName))        {            Debug.LogError("场景中没有此UI:" + uiName);            return;        }         if (destroy)        {            GameObject.Destroy(uiDict[uiName].gameObject);            uiDict.Remove(uiName);        }        else        {            uiDict[uiName].OnDisView();        }         FindTopUI();    }     /// <summary>    /// 敞开UI    /// </summary>    public void CloseUI<T>(bool destroy = false)    {        string uiName = typeof(T).Name;        if (!uiDict.ContainsKey(uiName))        {            Debug.LogError("场景中没有此UI:" + uiName);            return;        }         if (destroy)        {            GameObject.Destroy(uiDict[uiName].gameObject);            uiDict.Remove(uiName);        }        else        {            uiDict[uiName].OnDisView();        }         FindTopUI();    }     /// <summary>    /// 查找UI    /// </summary>    public T FindUI<T>()        where T : UIBase    {        string uiName = typeof(T).Name;        if (!uiDict.ContainsKey(uiName))        {            Debug.LogError("场景中没有此UI:" + uiName);            return default;        }        return uiDict[uiName] as T;    }     /// <summary>    /// 查找最顶部的UI    /// </summary>    private void FindTopUI()    {        for (int i = uiCanvas.transform.childCount - 1; i >= 0; i--)        {            if (uiCanvas.transform.GetChild(i).GetComponent<UIBase>() != null                && uiCanvas.transform.GetChild(i).gameObject.activeSelf)            {                topUI = uiCanvas.transform.GetChild(i).GetComponent<UIBase>();                break;            }        }    }     /// <summary>    /// 设置Canvas缩放    /// </summary>    /// <param name="referResolution">参考的分辨率</param>    /// <param name="isLandscape">是否为横屏</param>    public void SetCanvasScaler(Vector2 referResolution, bool isLandscape)    {        CanvasScaler canvasScaler = uiCanvas.GetComponent<CanvasScaler>();        canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;        canvasScaler.matchWidthOrHeight = isLandscape ? 1 : 0;        canvasScaler.referenceResolution = referResolution;    }     /// <summary>    /// 创立UI    /// </summary>    private void CreateUI(string uiName, string uiRoot)    {        string path = UIDir + uiName;        GameObject uiPrefab = Resources.Load<GameObject>(path);        if (uiPrefab == null)        {            Debug.LogError("UI不存在:" + path);            return;        }        UIBase uiBase = GameObject.Instantiate(uiPrefab, uiRoot == "" ? uiCanvas.transform : GameObject.Find(uiRoot).transform).GetComponent<UIBase>();        uiBase.gameObject.name = uiName;        uiDict.Add(uiName, uiBase);    }     /// <summary>    /// 创立UI画布    /// </summary>    private Canvas CreateUICanvas()    {        GameObject uiCanvas = new GameObject("UICanvas");        uiCanvas.layer = 5;        Canvas canvas = uiCanvas.AddComponent<Canvas>();        canvas.renderMode = RenderMode.ScreenSpaceCamera;        canvas.worldCamera = uiCamera;        uiCanvas.AddComponent<CanvasScaler>();        uiCanvas.AddComponent<GraphicRaycaster>();         GameObject eventSystem = new GameObject("EventSystem");        eventSystem.AddComponent<EventSystem>();        eventSystem.AddComponent<StandaloneInputModule>();        eventSystem.transform.SetParent(uiCanvas.transform);         GameObject.DontDestroyOnLoad(uiCanvas);        return uiCanvas.GetComponent<Canvas>();    }     /// <summary>    /// 创立UI相机    /// </summary>    private Camera CreateUICamera()    {        GameObject uiCamera = new GameObject("UICamera");        Camera camera = uiCamera.AddComponent<Camera>();        camera.clearFlags = CameraClearFlags.Depth;        camera.cullingMask = 1 << 5;        camera.orthographic = true;        camera.depth = 0;         GameObject.DontDestroyOnLoad(uiCamera);        return camera;    }}

图片起源:游戏加盟