共计 4456 个字符,预计需要花费 12 分钟才能阅读完成。
一:目标
在制作游戏过程中,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;
}
}
图片起源:游戏加盟
正文完