UI系统

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

public class UIManager : MonoBehaviour {

    private static UIManager _Instance;
    public static UIManager GetInstance()
    {
        if (_Instance == null)  { InitRoot(); }
        return _Instance;
    }
    private Dictionary<string, string> _allUINameAndPath;   //key:UI名称,value:UI的预制体的加载路径。初始化的时候填写
    private Dictionary<string, UITypeBase> _allUI;          //key:UI名称,UI对象。使用的时候动态添加
    private List<string> _simpleUIStack;                    //保存通过按钮等弹出的界面的集合,不包含初始化后就固定显示不动的UI。

    void Awake()
    {
        _Instance = this;
        InitAllUINameAndPath();
    }

    /// <summary>
    /// 创建Canvas,SystemEvent,UICamera,注意方法里面摄像机的分辨率写的是800,600
    /// </summary>
    static void InitRoot()
    {
        //创建一个物体来挂在此TTUIRoot组件
        GameObject go = new GameObject("Canvas");
        go.layer = LayerMask.NameToLayer("UI");
        _Instance = go.AddComponent<UIManager>();
        go.AddComponent<RectTransform>();
        //创建Canvas
        Canvas can = go.AddComponent<Canvas>();
        can.renderMode = RenderMode.ScreenSpaceCamera;
        can.pixelPerfect = true;
        //添加这个组件,一般创建Canvas的几件套
        go.AddComponent<GraphicRaycaster>();
        //给此脚本的root变量设置为本身

        //创建UI摄像机,后面的都是一些设置参数
        GameObject camObj = new GameObject("UICamera");
        camObj.layer = LayerMask.NameToLayer("UI");
        camObj.transform.parent = go.transform;
        camObj.transform.localPosition = new Vector3(0, 0, -100f);
        Camera cam = camObj.AddComponent<Camera>();
        cam.clearFlags = CameraClearFlags.Depth;
        cam.orthographic = true;
        cam.farClipPlane = 200f;
        can.worldCamera = cam;
        cam.cullingMask = 1 << 5;
        cam.nearClipPlane = -50f;
        cam.farClipPlane = 50f;


        //添加监听,和GUILayer组件
        //camObj.AddComponent<AudioListener>();
        camObj.AddComponent<GUILayer>();
        //这个也是Canvas的几件套之一,按照平时创建的一一填写即可
        CanvasScaler cs = go.AddComponent<CanvasScaler>();
        cs.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
        cs.referenceResolution = new Vector2(800, 600f);
        cs.screenMatchMode = CanvasScaler.ScreenMatchMode.Expand;


        //add Event System
        GameObject esObj = GameObject.Find("EventSystem");
        if (esObj != null)
        {
            GameObject.DestroyImmediate(esObj);
        }

        GameObject eventObj = new GameObject("EventSystem");
        eventObj.layer = LayerMask.NameToLayer("UI");
        eventObj.transform.SetParent(go.transform);
        eventObj.AddComponent<EventSystem>();
        eventObj.AddComponent<UnityEngine.EventSystems.StandaloneInputModule>();

    }

    /// <summary>
    /// 初始化存放 UI名称,UI路径 的字典_allUINameAndPath,或者读josn来存储
    /// </summary>
    void InitAllUINameAndPath()
    {
        _allUINameAndPath = new Dictionary<string, string>();
        _allUINameAndPath.Add(GlobeParameter.UIName_MenuButton,GlobeParameter.UIPath_MenuButton);
        _allUINameAndPath.Add(GlobeParameter.UIName_MenuPanel, GlobeParameter.UIPath_MenuPanel);
        _allUINameAndPath.Add(GlobeParameter.UIName_OpertionButton, GlobeParameter.UIPath_OpertionButton);
        _allUINameAndPath.Add(GlobeParameter.UIName_GameOverPanel, GlobeParameter.UIPath_GameOverPanel);
        _allUINameAndPath.Add(GlobeParameter.UIName_FoodFullImage, GlobeParameter.UIPath_FoodFullImage);
        _allUINameAndPath.Add(GlobeParameter.UIName_DangerCountDown, GlobeParameter.UIPath_DangerCountDown);
    }

    /// <summary>
    /// 显示UI
    /// </summary>
    /// <param name="uiName"> UI名称</param>
    public void ShowUI(string uiName)
    {
        if (string.IsNullOrEmpty(uiName) || _allUINameAndPath.ContainsKey(uiName) == false) 
        {
            return;
        }

        UITypeBase uiTypeBase = null;
        if (_allUI == null)
        {
            _allUI = new Dictionary<string, UITypeBase>();
        }
        if (_simpleUIStack == null)
        {
            _simpleUIStack = new List<string>();
        }

        if (_allUI.ContainsKey(uiName)) 
        {
            uiTypeBase = _allUI[uiName];
            //打开的情况下,再次点击就关闭UI
            if (uiTypeBase._isActive == true && _allUI[uiName].UIShowMode != UIShowMode.ShowTimeLimit)
            { 
                Hide(uiName);
                return;
            }
        }
        else if (_allUI.ContainsKey(uiName) == false)
        {
            uiTypeBase = InstantiateUIPrefab(uiName);
        }

        switch (uiTypeBase.UIShowMode)
        {
            case UIShowMode.Fixed:         
                break;
            case UIShowMode.Noraml:
                _simpleUIStack.Add(uiName);
                break;
            case UIShowMode.HideOther:
                HideOther(uiName);
                _simpleUIStack.Add(uiName);
                break;
            case UIShowMode.ShowTimeLimit:
                if (_simpleUIStack.Contains(uiName))
                {
                    StopCoroutine("HideDelay");
                }
                else
                {
                    _simpleUIStack.Add(uiName);
                }
                //ChangeUIPosition(uiName);
                StartCoroutine("HideDelay", uiName);
                break;
        }

        Active(uiName);
    }

    /// <summary>
    /// 显示UI: 物体挂载脚本里的数据,传递到UI界面更新数据用。
    /// </summary>
    /// <param name="uiName"> UI的名字</param>
    /// <param name="g"> 挂载数据脚本的物体</param>
    public void ShowUI(string uiName, GameObject g)
    {
        ShowUI(uiName);
        Active(uiName, g);
    }

    /// <summary>
    /// 改变UI的位置,预制体的UI是在原点,改变成鼠标的点击位置。
    /// </summary>
    /// <param name="uiName"></param>
    public void ChangeUIPosition(string uiName)
    {
        Vector2 _pos = Vector2.one;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(gameObject.GetComponent<Canvas>().transform as RectTransform,
                    Input.mousePosition, gameObject.GetComponent<Canvas>().worldCamera, out _pos);
        _allUI[uiName].GetComponent<RectTransform>().anchoredPosition = _pos;
    }

    /// <summary>
    /// 延迟隐藏UI
    /// </summary>
    /// <param name="uiName"> UI名称</param>
    /// <param name="time"> 延迟时间</param>
    /// <returns></returns>
    IEnumerator HideDelay(string uiName)
    {
        yield return new WaitForSeconds(3f);
        Hide(uiName);
    }

    /// <summary>
    /// 隐藏UI
    /// </summary>
    /// <param name="uiName"></param>
    public void Hide(string uiName)
    {

        UITypeBase uiTypeBase = _allUI[uiName];
        if (uiTypeBase._isActive == true)
        {
            uiTypeBase.Hide();
            _simpleUIStack.Remove(uiName);
        }

    }

    /// <summary>
    /// 除了参数以外的所有能隐藏的UI(Fixed类型的UI是不能隐藏),都隐藏
    /// </summary>
    /// <param name="uiName"></param>
    public void HideOther(string uiName)
    {
        if (_simpleUIStack != null) 
        {
            foreach (string s in _simpleUIStack)
            {
                if (s != uiName || _allUI[uiName].UIShowMode == UIShowMode.ShowTimeLimit)  
                {
                    _allUI[s].Hide();
                }
            }
            //清空栈
            _simpleUIStack.Clear();
        }
    }

    public void Reflush(string uiName)
    {
        _allUI[uiName].Active();
    }

    public void Reflush(string uiName,GameObject g)
    {
        _allUI[uiName].Active(g);
    }

    public void ReflushAsync(string uiName, GameObject g)
    {
        _allUI[uiName].RefreshAsync(g);
    }

    /// <summary>
    /// 异步刷新UI
    /// </summary>
    /// <param name="uiName"></param>

    /// <summary>
    /// 激活UI
    /// </summary>
    /// <param name="name">UI名称</param>
    void Active(string name)
    {
        _allUI[name].Active();
    }

    void Active(string name, GameObject g)
    {
        _allUI[name].Active(g);
    }

    /// <summary>
    /// 根据名称实例化UI
    /// </summary>
    /// <param name="name"></param>
    UITypeBase InstantiateUIPrefab(string name)
    {        
        string path = _allUINameAndPath[name];
        GameObject g = GameObject.Instantiate(Resources.Load(path)) as GameObject;
        g.name = name;
        g.transform.SetParent(gameObject.transform, false);

        if (g.GetComponent<UITypeBase>() == false)
        {
            Debug.LogError("物体" + g.name + "没有挂载相关脚本");
            return null;
        }

        UITypeBase uiTypeBase = g.GetComponent<UITypeBase>();
        _allUI.Add(name,uiTypeBase);
        return uiTypeBase;
    }

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

/*
 * 所有UI都继承自UITypeBase
 * 如有特殊需要就重写生命周期方法如Reflush(),Active(),Hide()
 * 所有UI都要选择自己的UIShowMode,
 * Fixed:可用于固定的窗口,如主界面,
 * Noraml:可用于普通的可以共同显示的UI
 * HideOther:只能独立显示在屏幕的,其中不包含Fixed类型的UI
 */
public abstract class UITypeBase : MonoBehaviour
{
    public UIShowMode UIShowMode;
    public bool _isActive = false;
    #region virtual method
    /// <summary>
    /// 激活
    /// </summary>
    public virtual void Active()
    {
        _isActive = true;
        this.gameObject.SetActive(true);
        Refresh();
    }

    /// <summary>
    /// 更新UI数据
    /// </summary>
    public virtual void Refresh()
    {

    }

    public virtual void Active(GameObject g)
    {
        _isActive = true;
        this.gameObject.SetActive(true);
        Refresh(g);
    }

    public virtual void Refresh(GameObject g)
    {

    }

    public virtual void RefreshAsync(GameObject g)
    {

    }

    /// <summary>
    /// 隐藏
    /// </summary>
    public virtual void Hide()
    {
        _isActive = false;
        this.gameObject.SetActive(false);
    }
    #endregion

}

public enum UIShowMode
{
    Fixed,          //固定窗口
    Noraml,         //普通窗口
    HideOther,      //隐藏其他窗口
    ShowTimeLimit,  //显示限制时间,仅显示若干秒关闭,或者点击其他就关闭这个模式的UI
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值