版权声明:转载或者引用本文内容请注明来源及原作者 https://blog.csdn.net/TIANHUNYISHUI/article/details/88814853
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Framework {
/// <summary>
/// UI系统
/// </summary>
[RequireComponent (typeof (Canvas), typeof (CanvasScaler), typeof (GraphicRaycaster))]
[RequireComponent (typeof (UnityEngine.EventSystems.EventSystem), typeof (StandaloneInputModule))]
public class UISystem : MonoSingleton<UISystem> {
/// <summary>
/// 名字分隔符
/// </summary>
private const char SPLIT_NAME = '.';
/// <summary>
/// 画布对象
/// </summary>
public static Canvas Canvas { get; private set; }
/// <summary>
/// 画布缩放对象
/// </summary>
public static CanvasScaler CanvasScaler { get; private set; }
/// <summary>
/// 图像射线接收器
/// </summary>
public static GraphicRaycaster GraphicRaycaster { get; private set; }
/// <summary>
/// 引擎事件系统
/// </summary>
public static UnityEngine.EventSystems.EventSystem EventSystem { get; private set; }
/// <summary>
/// UI摄像机
/// </summary>
public static Camera Camera { get { return Canvas == null ? null : Canvas.worldCamera; } }
/// <summary>
/// 画布大小
/// </summary>
public static Vector2 CanvasSize { get { return (Instance.transform as RectTransform).sizeDelta; } }
/// <summary>
/// 屏幕到UI缩放比例
/// </summary>
public static Vector2 ScreenToUIScale { get { return new Vector2 (CanvasSize.x / Screen.width, CanvasSize.y / Screen.height); } }
/// <summary>
/// UI到屏幕缩放比例
/// </summary>
public static Vector2 UIToScreenScale { get { return new Vector2 (Screen.width / CanvasSize.x, Screen.height / CanvasSize.y); } }
/// <summary>
/// 世界到UI缩放比例
/// </summary>
public static Vector2 WorldToUIScale { get { return new Vector2 (1 / Canvas.transform.localScale.x, 1 / Canvas.transform.localScale.y); } }
/// <summary>
/// UI到世界缩放比例
/// </summary>
public static Vector2 UIToWorldScale { get { return new Vector2 (Canvas.transform.localScale.x, Canvas.transform.localScale.y); } }
/// <summary>
/// 世界到屏幕缩放比例
/// </summary>
public static Vector2 WorldToScreenScale { get { return new Vector2 (WorldToScreenScale.x * UIToScreenScale.x, WorldToScreenScale.y * UIToScreenScale.y); } }
/// <summary>
/// 屏幕到世界缩放比例
/// </summary>
public static Vector2 ScreenToWorldScale { get { return new Vector2 (ScreenToUIScale.x * UIToWorldScale.x, ScreenToUIScale.y * UIToWorldScale.y); } }
/// <summary>
/// 面板表[键:面板名 值:面板对象]
/// </summary>
private Dictionary<string, UIPanel> m_PanelMap = new Dictionary<string, UIPanel> ();
/// <summary>
/// 面板链表
/// </summary>
private List<UIPanel> m_PanelList = new List<UIPanel> ();
/// <summary>
/// 异步回调表[键:面板名 值:回调]
/// </summary>
private Dictionary<string, Action<UIPanel>> m_AsyncCallbackMap = new Dictionary<string, Action<UIPanel>> ();
/// <summary>
/// 初始化
/// </summary>
/// <param name="renderMode">渲染模式</param>
/// <param name="camera">摄像机</param>
/// <param name="scaleMode">缩放模式</param>
/// <param name="resolution">自适应分辨率</param>
public static void Init (RenderMode renderMode,
Camera camera,
CanvasScaler.ScaleMode scaleMode,
Vector2 resolution) {
Canvas = Instance.gameObject.GetComponent<Canvas> ();
CanvasScaler = Instance.gameObject.GetComponent<CanvasScaler> ();
GraphicRaycaster = Instance.gameObject.GetComponent<GraphicRaycaster> ();
EventSystem = Instance.gameObject.GetComponent<UnityEngine.EventSystems.EventSystem> ();
Canvas.planeDistance = 0;
Canvas.renderMode = renderMode;
Canvas.worldCamera = camera;
CanvasScaler.uiScaleMode = scaleMode;
CanvasScaler.referenceResolution = resolution;
}
/// <summary>
/// 打开面板
/// </summary>
/// <param name="panelName">面板名</param>
/// <param name="type">面板类型</param>
/// <returns></returns>
public static UIPanel Open (string panelName, Type type) {
UIPanel panel = Get (panelName);
if (panel == null) {
GameObject asset = null;
asset = Resources.Load<GameObject> (panelName);
GameObject gameObject = Instantiate (asset);
gameObject.name = asset.name;
gameObject.transform.SetParent (Instance.transform, false);
panel = Activator.CreateInstance (type) as UIPanel;
panel.Init (panelName, gameObject);
Instance.m_PanelMap[panelName] = panel;
Instance.m_PanelList.Add (panel);
}
panel.Enabled = true;
return panel;
}
/// <summary>
/// 异步打开面板
/// </summary>
/// <param name="panelName">面板名</param>
/// <param name="type">面板类型</param>
/// <param name="openCallback">打开回调</param>
public static void OpenAsync (string panelName, Type type, Action<UIPanel> openCallback = null) {
UIPanel panel = Get (panelName);
if (panel == null) {
Action<UIPanel> callback = null;
if (Instance.m_AsyncCallbackMap.TryGetValue (panelName, out callback)) {
callback -= openCallback;
callback += openCallback;
Instance.m_AsyncCallbackMap[panelName] = callback;
} else {
Instance.m_AsyncCallbackMap[panelName] = openCallback;
Instance.StartCoroutine (OnLoadComplete (panelName, type));
}
} else {
if (openCallback != null) {
openCallback.Invoke (panel);
}
panel.Enabled = true;
}
}
/// <summary>
/// 更新启用的面板
/// </summary>
private void Update () {
if (m_PanelList != null) {
foreach (var panel in m_PanelList) {
if (!panel.Enabled)
continue;
panel.OnUpdate ();
}
}
}
/// <summary>
/// 关闭面板
/// </summary>
/// <param name="panelName">面板名</param>
/// <param name="destroy">是否销毁</param>
public static void Close (string panelName, bool destroy = false) {
UIPanel panel = Get (panelName);
if (panel == null) {
return;
}
if (destroy) {
Instance.m_PanelMap.Remove (panelName);
Instance.m_PanelList.Remove (panel);
panel.OnDestroy ();
Destroy (panel.GameObject);
} else {
panel.Enabled = false;
}
}
/// <summary>
/// 获取面板
/// </summary>
/// <param name="panelName">面板名</param>
/// <returns>返回面板</returns>
public static UIPanel Get (string panelName) {
UIPanel panel = null;
Instance.m_PanelMap.TryGetValue (panelName, out panel);
return panel;
}
/// <summary>
/// 获取所有面板
/// </summary>
/// <returns></returns>
public static UIPanel[] GetAll () {
return Instance.m_PanelList.ToArray ();
}
/// <summary>
/// 销毁启用的面板
/// </summary>
private void OnDestroy () {
if (m_PanelList != null) {
foreach (var panel in m_PanelList) {
if (!panel.Enabled)
continue;
panel.OnDestroy ();
}
}
}
/// <summary>
/// 屏幕转UI坐标
/// </summary>
/// <param name="position">屏幕坐标</param>
/// <returns>返回UI坐标</returns>
public static Vector2 ScreenToUIPoint (Vector2 position) {
RectTransform transform = Instance.transform as RectTransform;
Vector2 point = new Vector2 ((position.x / Screen.width - 0.5f) * transform.sizeDelta.x,
(position.y / Screen.height - 0.5f) * transform.sizeDelta.y);
return point;
}
/// <summary>
/// UI转屏幕坐标
/// </summary>
/// <param name="position"></param>
/// <returns></returns>
public static Vector2 UIToScreenPoint (Vector2 position) {
RectTransform transform = Instance.transform as RectTransform;
Vector2 point = new Vector2 ((position.x / transform.sizeDelta.x + 0.5f) * Screen.width,
(position.y / transform.sizeDelta.y + 0.5f) * Screen.height);
return point;
}
/// <summary>
/// 世界转UI坐标
/// </summary>
/// <param name="position">世界坐标</param>
/// <returns>返回UI坐标</returns>
public static Vector2 WorldToUIPoint (Vector3 position) {
Vector2 screenPosition = WorldToScreenPoint (position);
return ScreenToUIPoint (screenPosition);
}
/// <summary>
/// UI转世界坐标
/// </summary>
/// <param name="position">UI坐标</param>
/// <returns>返回世界坐标</returns>
public static Vector3 UIToWorldPoint (Vector2 position) {
Vector2 screenPosition = UIToScreenPoint (position);
return ScreenToWorldPoint (screenPosition);
}
/// <summary>
/// 世界转屏幕坐标
/// </summary>
/// <param name="position">世界坐标</param>
/// <returns>返回屏幕坐标</returns>
public static Vector3 WorldToScreenPoint (Vector3 position) {
return Camera.WorldToScreenPoint (position);
}
/// <summary>
/// 屏幕转世界坐标
/// </summary>
/// <param name="position">屏幕坐标</param>
/// <returns>返回世界坐标</returns>
public static Vector3 ScreenToWorldPoint (Vector3 position) {
return Camera.ScreenToWorldPoint (position);
}
/// <summary>
/// 加载完成回调
/// </summary>
/// <param name="asset"></param>
/// <param name="arg"></param>
private static void OnLoadComplete (object asset, object arg) {
GameObject uiAsset = asset as GameObject;
GameObject gameObject = Instantiate (uiAsset);
gameObject.name = uiAsset.name;
gameObject.transform.SetParent (Instance.transform, false);
object[] args = arg as object[];
string panelName = args[0] as string;
Type type = args[1] as Type;
UIPanel panel = Activator.CreateInstance (type) as UIPanel;
panel.Init (panelName, gameObject);
Instance.m_PanelMap[panelName] = panel;
Instance.m_PanelList.Add (panel);
panel.Enabled = true;
Action<UIPanel> openCallback = Instance.m_AsyncCallbackMap[panelName];
if (openCallback != null) {
openCallback.Invoke (panel);
Instance.m_AsyncCallbackMap.Remove (panelName);
}
}
/// <summary>
/// 异步加载完成回调
/// </summary>
/// <param name="panelName"></param>
/// <param name="type"></param>
/// <returns></returns>
private static IEnumerator OnLoadComplete (string panelName, Type type) {
ResourceRequest request = Resources.LoadAsync<GameObject> (panelName);
yield return request;
try {
GameObject gameObject = Instantiate (request.asset as GameObject);
gameObject.name = request.asset.name;
gameObject.transform.SetParent (Instance.transform, false);
UIPanel panel = Activator.CreateInstance (type) as UIPanel;
panel.Init (panelName, gameObject);
Instance.m_PanelMap[panelName] = panel;
Instance.m_PanelList.Add (panel);
panel.Enabled = true;
Action<UIPanel> openCallback = Instance.m_AsyncCallbackMap[panelName];
if (openCallback != null) {
openCallback.Invoke (panel);
Instance.m_AsyncCallbackMap.Remove (panelName);
}
} catch (Exception e) {
Debug.LogError ("异步打开界面错误!" + panelName + " " + e);
}
}
}
}