unity3d基于ugui的ui模块

对于u3d客户端最好的学习方法就是实践!!
今天终于有时间可以写写博客,这次我写一个基于ugui的ui模块,也可以理解为封装,把ui相关封装起来方便使用。
回到正题!
首先我会用到单例模式,不懂的自行百度。我这里添加一个创建gameobject的单例。

using UnityEngine;
using System.Collections;

public class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
    protected static readonly T instance = Create();
    public static T GetSingleton()
    {
        return instance;
    }

    private static T Create()
    {
        T instance = GameObject.FindObjectOfType<T>();
        if (null == instance)
        {
            instance = new GameObject(typeof(T).Name + "_Singleton").AddComponent<T>();
        }
        GameObject.DontDestroyOnLoad(instance);
        return instance;
    }

    protected static V AddComponent<V>() where V : MonoBehaviour
    {
        return instance.gameObject.AddComponent<V>();
    }
}

1.ui我采用的是ngui那种双摄像机,首先创建一个ui摄像机的单例吧

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Camera))]
public class UICamera : MonoSingleton<UICamera>
{
    public Camera UI_Camera { get; set; }

    void Awake()
    {
        UI_Camera = GetComponent<Camera>();
        UI_Camera.clearFlags = CameraClearFlags.Depth;
        UI_Camera.cullingMask = 1 << LayerMask.NameToLayer("UI");
        UI_Camera.orthographic = true;
        UI_Camera.orthographicSize = 3.2f;
    }
}

然后测试一下这个单例
这里写图片描述
测试结果
这里写图片描述

2.基本东西已经准备好了,现在开始书写我们的ui框架
ui基本框架有三个东西
这里写图片描述
UISystem :管理ui,包括创建ui,查找ui,删除ui等等(其他功能可以自己扩展)
UIWidget:处理ui逻辑,注册ui事件(点击,拖拽之类),设置sprite、设置label等等接口(很多功能可以自己扩展,例如:点击音效,ui动画)
IEventListener : 是对EventTrigger进行下一层封装,封装成类似ngui事件监听

看UISystem的代码之前,我要补充一下,RectTransformUtility.CalculateRelativeRectTransformBounds可以计算ui的包围盒,不过他的大小位置是根据屏幕缩放之前的rect。 Canvas获取RectTransform. rect是屏幕缩放过的rect,因为我是按照高度适应,所以根据高度来算出比例来算出屏幕缩放之前rect,根据包围盒和Canvas的rect可以用来判断ui是否超出界面,判断超出有什么用?例如:物品属性面板是跟着物品图标位置改变而改变,如果靠太边,属性面板就会超出屏幕。如果超出会做相应工作把他放在屏幕内,这个代码已经写好,下次放出。
计算缩放前的rect代码如下
这里写图片描述

UISystem代码

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

[RequireComponent(typeof(Canvas))]
[RequireComponent(typeof(CanvasScaler))]
[RequireComponent(typeof(GraphicRaycaster))]
[RequireComponent(typeof(EventSystem))]
[RequireComponent(typeof(StandaloneInputModule))]
[RequireComponent(typeof(TouchInputModule))]
public sealed class UISystem : MonoSingleton<UISystem>
{
    public const int WIDTH = 960;
    public const int HEIGHT = 640;

    public Canvas Canvas { get; set; }
    public CanvasScaler CanvasScaler { get; set; }
    public Camera UI_Camera { get; set; }
    public RectTransform UIRectTranform { get; set; }
    public Rect UI_Rect { get; set; }

    /// <summary>
    /// 存放由uisystem创建的ui
    /// </summary>
    private Dictionary<string, UIWidget> m_UI_Dic = new Dictionary<string, UIWidget>();

    void Awake()
    {
        this.gameObject.layer = LayerMask.NameToLayer("UI");
        this.Canvas = GetComponent<Canvas>();
        this.CanvasScaler = GetComponent<CanvasScaler>();
        this.UI_Camera = UICamera.GetSingleton().UI_Camera;

        this.Canvas.renderMode = RenderMode.ScreenSpaceCamera;
        this.Canvas.worldCamera = UI_Camera;

        this.CanvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
        this.CanvasScaler.matchWidthOrHeight = 1;
        this.CanvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
        this.CanvasScaler.referenceResolution = new Vector2(WIDTH, HEIGHT);

        this.UIRectTranform = GetComponent<RectTransform>();

        Rect screenRect = UIRectTranform.rect;
        float scale = CanvasScaler.matchWidthOrHeight == 1 ? (float)HEIGHT / (float)Screen.height : (float)WIDTH / (float)Screen.width;
        UI_Rect = new Rect(screenRect.x * scale, screenRect.y * scale, screenRect.width * scale, screenRect.height * scale);
    }

    /// <summary>
    /// 创建ui控件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="resourcePath"></param>
    /// <param name="visable"></param>
    /// <returns></returns>
    public T CreateWight<T>(string resourcePath,bool visable = true) where T : UIWidget
    {
        T panel = null;

        if (m_UI_Dic.ContainsKey(resourcePath))
        {
            panel = GetWidget<T>(resourcePath);
            panel.SetVisable(visable);
            panel.rectTransform.SetAsLastSibling();
            return panel;
        }

        panel = CreateResource(resourcePath, transform).AddComponent<T>();
        panel.SetVisable(visable);
        panel.rectTransform.SetAsLastSibling();

        panel.rectTransform.sizeDelta = Vector2.zero;
        panel.rectTransform.anchoredPosition = Vector3.zero;
        panel.transform.localScale = Vector3.one;

        m_UI_Dic[resourcePath] = panel;

        return panel;
    }

    /// <summary>
    /// 创建一个ui控件
    /// </summary>
    /// <param name="resoucePath"></param>
    /// <param name="parent"></param>
    /// <returns></returns>
    public GameObject CreateWidget(string resoucePath,Transform parent)
    {
        GameObject go = CreateResource(resoucePath,parent);
        RectTransform rt = go.GetComponent<RectTransform>();
        rt.anchoredPosition = Vector2.zero;
        rt.localScale = Vector3.one;
        return go;
    }

    /// <summary>
    /// 获取ui控件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="resourcePath"></param>
    /// <returns></returns>
    public T GetWidget<T>(string resourcePath) where T : UIWidget
    {
        if (!m_UI_Dic.ContainsKey(resourcePath)) { return null; }
        if (null == m_UI_Dic[resourcePath]) { return null; }
        return m_UI_Dic[resourcePath] as T;
    }

    /// <summary>
    /// 创建ui的游戏对象
    /// </summary>
    /// <param name="resourcePath"></param>
    /// <param name="parent"></param>
    /// <returns></returns>
    private GameObject CreateResource(string resourcePath,Transform parent)
    {
        GameObject resource = Resources.Load(resourcePath) as GameObject;

        if (null == resource)
        {
            throw new System.NullReferenceException(resourcePath);
        }

        GameObject widget = (GameObject)Instantiate(resource);

        widget.name = resourcePath;
        widget.transform.parent = parent;
        return widget;
    }

    /// <summary>
    /// 删除创建的ui
    /// </summary>
    /// <param name="resourcePath"></param>
    public void DestoryWidget(string resourcePath)
    {
        if (!m_UI_Dic.ContainsKey(resourcePath)) { return; }
        if (null == m_UI_Dic[resourcePath]) { m_UI_Dic.Remove(resourcePath); }
        Destroy(m_UI_Dic[resourcePath].gameObject);
        m_UI_Dic.Remove(resourcePath);
    }
}

UIWidget代码,注册事件我添加了一个根据ui名字注册和gameobject注册,其实都是gameobject注册 ,里面只添加了点击事件,其他事件可以自己添加。部分接口隐藏ui,显示ui,设置精灵,设置文字等等接口

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

public class UIWidget : MonoBehaviour
{
    protected Dictionary<string, GameObject> m_Widgets = new Dictionary<string, GameObject>();

    public const string CONTAIN_WORLD = "UI";

    /// <summary>
    /// 初始化控件
    /// </summary>
    /// <param name="aryName"></param>
    protected void InstallWidgets(string[] aryName)
    {
        List<RectTransform> trans = new List<RectTransform>(gameObject.GetComponentsInChildren<RectTransform>());
        for (int i = 0; i < aryName.Length; i++)
        {
            for (int j = 0; j < trans.Count; j++)
            {
                if (trans[j].name == aryName[i])
                {
                    m_Widgets[aryName[i]] = trans[j].gameObject;
                    trans.RemoveAt(j);
                    break;
                }
            }
        }
    }

    /// <summary>
    /// 当前面板的rect
    /// </summary>
    public RectTransform rectTransform
    {
        get
        {
            if(null == m_RectTransform)
            {
                m_RectTransform = GetComponent<RectTransform>();
            }
            return m_RectTransform;
        }
    }
    private RectTransform m_RectTransform;

    /// <summary>
    /// 查找ui控件接口
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public GameObject Find(string name)
    {
        if (!m_Widgets.ContainsKey(name)) { return null; }
        return m_Widgets[name];
    }

    /// <summary>
    /// 通过gameobject注册点击事件
    /// </summary>
    /// <param name="go"></param>
    /// <param name="execute"></param>
    public void RegisterClickEvent(GameObject go, UIEventListener.VoidDelegate execute)
    {
        if (null == go) { return; }
        UIEventListener.Get(go).onPointerClick = execute;
    }

    /// <summary>
    /// 通过控件名称注册点击事件
    /// </summary>
    /// <param name="widget"></param>
    /// <param name="execute"></param>
    public void RegisterClickEvent(string widget, UIEventListener.VoidDelegate execute)
    {
        RegisterClickEvent(Find(widget), execute);
    }

    /// <summary>
    /// 设置精灵
    /// </summary>
    /// <param name="go"></param>
    /// <param name="sprite"></param>
    public void SetSprite(GameObject go,Sprite sprite)
    {
        if (null == go) { return; }
        Image image = go.GetComponent<Image>();
        if (null == image) { return; }
        image.sprite = sprite;
    }

    public void SetSprite(string widget, Sprite sprite)
    {
        SetSprite(Find(widget), sprite);
    }

    /// <summary>
    /// 设置进度条
    /// </summary>
    /// <param name="go"></param>
    /// <param name="value"></param>
    public void SetSlider(GameObject go,float value)
    {
        if (null == go) { return; }
        Slider slider = go.GetComponent<Slider>();
        if (null == slider) { return; }
        slider.value = value;
    }

    public void SetSlider(string widget, float value)
    {
        SetSlider(Find(widget), value);
    }

    /// <summary>
    /// 设置toggle
    /// </summary>
    /// <param name="go"></param>
    /// <param name="enable"></param>
    public void SetToggle(GameObject go,bool enable)
    {
        if (null == go) { return; }
        Toggle toggle = go.GetComponent<Toggle>();
        if (null == toggle) { return; }
        toggle.isOn = enable;
    }

    public void SetToggle(string widget,bool enable)
    {
        SetToggle(Find(widget), enable);
    }

    /// <summary>
    /// 设置文字
    /// </summary>
    /// <param name="go"></param>
    /// <param name="content"></param>
    public void SetText(GameObject go,string content)
    {
        if (null == go) { return; }
        Text text = go.GetComponent<Text>();
        if (null == text) { return; }
        text.text = content;
    }

    public void SetText(string widget,string content)
    {
        SetText(Find(widget), content);
    }

    /// <summary>
    /// 设置输入文字
    /// </summary>
    /// <param name="go"></param>
    /// <param name="content"></param>
    public void SetInputText(GameObject go,string content)
    {
        if (null == go) { return; }
        InputField input = go.GetComponent<InputField>();
        if (null == input) { return; }
        input.text = content;
    }

    public void SetInputText(string widget,string content)
    {
        SetInputText(Find(widget), content);
    }

    /// <summary>
    /// 设置控件颜色
    /// </summary>
    /// <param name="go"></param>
    /// <param name="color"></param>
    public void SetColor(GameObject go,Color color)
    {
        if (null == go) { return; }
        Graphic graphic = go.GetComponent<Graphic>();
        if (null == graphic) { return; }
        graphic.color = color;
    }

    public void SetColor(string widget,Color color)
    {
        SetColor(Find(widget), color);
    }

    /// <summary>
    /// 获取进度条的value
    /// </summary>
    /// <param name="go"></param>
    /// <returns></returns>
    public float GetSliderValue(GameObject go)
    {
        if (null == go) { return 0; }
        Slider slider = go.GetComponent<Slider>();
        if (null == slider) { return 0; }
        return slider.value;
    }

    public float GetSliderValue(string widget)
    {
        return GetSliderValue(Find(widget));
    }

    /// <summary>
    /// 获取toggle状态
    /// </summary>
    /// <param name="go"></param>
    /// <returns></returns>
    public bool GetToggle(GameObject go)
    {
        if (null == go) { return false; }
        Toggle toggle = go.GetComponent<Toggle>();
        if (null == toggle) { return false; }
        return toggle.isOn;
    }

    public void GetToggle(string widget)
    {
        GetToggle(Find(widget));
    }

    /// <summary>
    /// 获取输入框的文字
    /// </summary>
    /// <param name="go"></param>
    /// <returns></returns>
    public string GetInputText(GameObject go)
    {
        if (null == go) { return string.Empty; }
        InputField input = go.GetComponent<InputField>();
        if (null == input) { return string.Empty; }
        return input.text;
    }

    public string GetInputText(string widget)
    {
        return GetInputText(Find(widget));
    }

    /// <summary>
    /// 显示控件
    /// </summary>
    /// <param name="name"></param>
    protected void Show(string name)
    {
        GameObject go = Find(name);
        if (null == go) { return; }
        go.SetActive(true);
    }

    /// <summary>
    /// 隐藏控件
    /// </summary>
    /// <param name="name"></param>
    protected void Hide(string name)
    {
        GameObject go = Find(name);
        if (null == go) { return; }
        go.SetActive(false);
    }

    public void SetVisable(bool visable)
    {
        gameObject.SetActive(visable);
    }
}

UIEventListener 代码
这个不多说看过用过ngui的都知道。我只是继承EventTrigger,然后重写方法而已

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;

public class UIEventListener : EventTrigger
{
    public delegate void VoidDelegate(GameObject go, BaseEventData eventData);
    public VoidDelegate onBeginDrag;
    public VoidDelegate onCancel;
    public VoidDelegate onDeSelect;
    public VoidDelegate onDrag;
    public VoidDelegate onDrop;
    public VoidDelegate onEndDrag;
    public VoidDelegate onInitializePotentialDrag;
    public VoidDelegate onMove;
    public VoidDelegate onPointerClick;
    public VoidDelegate onPointerDown;
    public VoidDelegate onPointerEnter;
    public VoidDelegate onPointerExit;
    public VoidDelegate onPointerUp;
    public VoidDelegate onScroll;
    public VoidDelegate onSelect;
    public VoidDelegate onSubmit;
    public VoidDelegate onUpdateSelect;

    public override void OnBeginDrag(PointerEventData eventData)
    {
        if(null != onBeginDrag) { onBeginDrag(gameObject, eventData); }
    }

    public override void OnCancel(BaseEventData eventData)
    {
        if (null != onCancel) { onCancel(gameObject, eventData); }
    }

    public override void OnDeselect(BaseEventData eventData)
    {
        if (null != onDeSelect) { onDeSelect(gameObject, eventData); }
    }

    public override void OnDrag(PointerEventData eventData)
    {
        if (null != onDrag) { onDrag(gameObject, eventData); }
    }

    public override void OnDrop(PointerEventData eventData)
    {
        if (null != onDrop) { onDrop(gameObject, eventData); }
    }

    public override void OnEndDrag(PointerEventData eventData)
    {
        if (null != onEndDrag) { onEndDrag(gameObject, eventData); }
    }

    public override void OnInitializePotentialDrag(PointerEventData eventData)
    {
        if (null != onInitializePotentialDrag) { onInitializePotentialDrag(gameObject, eventData); }
    }

    public override void OnMove(AxisEventData eventData)
    {
        if (null != onMove) { onMove(gameObject, eventData); }
    }

    public override void OnPointerClick(PointerEventData eventData)
    {
        if (null != onPointerClick) { onPointerClick(gameObject, eventData); }
    }

    public override void OnPointerDown(PointerEventData eventData)
    {
        if (null != onPointerDown) { onPointerDown(gameObject, eventData); }
    }

    public override void OnPointerEnter(PointerEventData eventData)
    {
        if (null != onPointerEnter) { onPointerEnter(gameObject, eventData); }
    }

    public override void OnPointerExit(PointerEventData eventData)
    {
        if (null != onPointerExit) { onPointerExit(gameObject, eventData); }
    }

    public override void OnPointerUp(PointerEventData eventData)
    {
        if (null != onPointerUp) { onPointerUp(gameObject, eventData); }
    }

    public override void OnScroll(PointerEventData eventData)
    {
        if (null != onScroll) { onScroll(gameObject, eventData); }
    }

    public override void OnSelect(BaseEventData eventData)
    {
        if (null != onSelect) { onSelect(gameObject, eventData); }
    }

    public override void OnSubmit(BaseEventData eventData)
    {
        if (null != onSubmit) { onSubmit(gameObject, eventData); }
    }

    public override void OnUpdateSelected(BaseEventData eventData)
    {
        if (null != onUpdateSelect) { onUpdateSelect(gameObject, eventData); }
    }

    static public UIEventListener Get(GameObject go)
    {
        UIEventListener listener = go.GetComponent<UIEventListener>();
        if (listener == null) listener = go.AddComponent<UIEventListener>();
        return listener;
    }
}

现在测试一下这个ui模块
首先添加一个ui预设先
这里写图片描述
然后预设路径放在
这里写图片描述
ui对应的脚本UITest
这里写图片描述
添加测试代码
这里写图片描述
运行效果,点击按钮就有打印
这里写图片描述
下期会放出ui超出屏幕的处理以及把ui位置设定在某个ui的8个方向的位置的计算

猜你喜欢

转载自blog.csdn.net/SnoopyNa2Co3/article/details/50409108