乐趣区

关于u3d:U3D游戏开发框架三UI管理器

一:目标
在制作游戏过程中,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;
    }
}

图片起源:游戏加盟

退出移动版