2019-12-10 19:48:49 zhunju0089 阅读数 24

详细讲解篇幅可能有点长,直接上图和资源(实现的具体步骤往下看)

GIF图看起来有点卡顿, 实际上运行是流畅的。

码云:https://gitee.com/NCAA_admin/Alert.git

具体实现步骤

1.创建一个背景图片Background并设置相应属性值

2.设置Canvas的属性和Game窗口的比例

3.创建一个弹窗的遮罩蒙版 名为Alert的Image,参数设置如下

4.在Alert下创建一个弹出的信息框 名为Message的Image,各参数设置如下

5.在Message下创建一个文本对象 Text,参数设置如下

6.接在也在Alert下创建两个按钮 Confirm和Cancel

7.其中两个按钮的Text参数分别如下

8.创建一个Shader的蒙版,在Assets下创建Shaders文件夹,在Shaders文件夹下创建名为Blur的Shader脚本

10.Shader脚本,内容如下(关于Shader的实现原理和步骤,有时间再做一个专题的解析)

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/Blur"
{
	// 属性
	Properties
	{
		// 定义 1-255 范围的半径 默认 1
		_Radius("Radius", Range(1, 255)) = 1
	}

	Category
	{
		Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Opaque" }

		SubShader
	{

	GrabPass
	{
		Tags{ "LightMode" = "Always" }
	}

	Pass
	{
		Tags{ "LightMode" = "Always" }
		
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#pragma fragmentoption ARB_precision_hint_fastest
		#include "UnityCG.cginc"

	struct appdata_t
	{
		float4 vertex : POSITION;
		float2 texcoord: TEXCOORD0;
	};

	struct v2f
	{
		float4 vertex : POSITION;
		float4 uvgrab : TEXCOORD0;
	};

	v2f vert(appdata_t v)
	{
		v2f o;
		o.vertex = UnityObjectToClipPos(v.vertex);
#if UNITY_UV_STARTS_AT_TOP
		float scale = -1.0;
#else
		float scale = 1.0;
#endif
		o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
		o.uvgrab.zw = o.vertex.zw;
		return o;
	}

	sampler2D _GrabTexture;
	float4 _GrabTexture_TexelSize;
	float _Radius;

	half4 frag(v2f i) : COLOR
	{
		half4 sum = half4(0,0,0,0);

#define GRABXYPIXEL(kernelx, kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely, i.uvgrab.z, i.uvgrab.w)))

		sum += GRABXYPIXEL(0.0, 0.0);
		int measurments = 1;

		for (float range = 0.1f; range <= _Radius; range += 0.1f)
		{
			sum += GRABXYPIXEL(range, range);
			sum += GRABXYPIXEL(range, -range);
			sum += GRABXYPIXEL(-range, range);
			sum += GRABXYPIXEL(-range, -range);
			measurments += 4;
		}

		return sum / measurments;
	}
		ENDCG
	}
		GrabPass
	{
		Tags{ "LightMode" = "Always" }
	}

		Pass
	{
		Tags{ "LightMode" = "Always" }

		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"

		struct appdata_t
	{
		float4 vertex : POSITION;
		float2 texcoord: TEXCOORD0;
	};

	struct v2f
	{
		float4 vertex : POSITION;
		float4 uvgrab : TEXCOORD0;
	};

	v2f vert(appdata_t v)
	{
		v2f o;
		o.vertex = UnityObjectToClipPos(v.vertex);
#if UNITY_UV_STARTS_AT_TOP
		float scale = -1.0;
#else
		float scale = 1.0;
#endif
		o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
		o.uvgrab.zw = o.vertex.zw;
		return o;
	}

	sampler2D _GrabTexture;
	float4 _GrabTexture_TexelSize;
	float _Radius;

	half4 frag(v2f i) : COLOR
	{

		half4 sum = half4(0,0,0,0);
		float radius = 1.41421356237 * _Radius;

#define GRABXYPIXEL(kernelx, kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely, i.uvgrab.z, i.uvgrab.w)))

		sum += GRABXYPIXEL(0.0, 0.0);
		int measurments = 1;

		for (float range = 1.41421356237f; range <= radius * 1.41; range += 1.41421356237f)
		{
			sum += GRABXYPIXEL(range, 0);
			sum += GRABXYPIXEL(-range, 0);
			sum += GRABXYPIXEL(0, range);
			sum += GRABXYPIXEL(0, -range);
			measurments += 4;
		}

		return sum / measurments;
	}
		ENDCG
	}
	}
	}
}

11.在Assets下创建一个名Materials文件夹,在Materials文件夹下创建名为MaskBlur的Material材质

12.在Alert下指定MaskBlur材质,并设置材质的模糊值为5

13.为了使交互效果具有动画的过度感,在编辑器顶部的菜单栏中 Windows>Asset Store 下打开资源商店

14.搜索DoTween关键词,并进入下载

15.下载完成后点击导入即可

16.在Assets下创建Scripts文件夹,在Scripts下创建Alert.cs脚本

17.Alert.cs脚本内容

using UnityEngine;
using DG.Tweening;
using UnityEngine.UI;
using UnityEngine.EventSystems;
//显示Alert会话
public class Alert : MonoBehaviour
{
    public static Alert Instance;
    private void Awake()
    {
        Instance = this;
    }
    [Tooltip("会话对象")] public RectTransform m_alert;
    //获取ui blur(alert)初始大小
    private Vector2 _uiBlurSize;
    //获取ui blur(alert)初始scale
    private Vector2 _uiBlurScale;
    //透明遮罩层
    private RectTransform _transparentMask;
    //透明遮罩层的初始颜色值值
    private Color _transparentMaskColor;
    //获取confirm
    private RectTransform _confirm;
    //获取confirm初始大小
    private Vector2 _confirmSize;
    //获取confirm初始scale
    private Vector2 _confirmScale;
    //获取text对象
    private Text _text;
    //获取text的大小
    private Vector2 _textSize;
    //获取text scale
    private Vector2 _textScale;
    void Start()
    {
        //判断并且赋值
        if (!m_alert)
        {
            m_alert = transform.GetComponent<RectTransform>();
        }
        //获取uiblur(alert)初始大小
        _uiBlurSize = m_alert.rect.size;
        _uiBlurScale = m_alert.localScale;
        //获取透明遮罩层
        _transparentMask = m_alert.GetChild(0).GetComponent<RectTransform>();
        //透明遮罩层的颜色
        _transparentMaskColor = _transparentMask.GetComponent<Image>().color;
        //获取confirm
        _confirm = m_alert.GetChild(1).GetComponent<RectTransform>();
        //获取confirm初始大小
        _confirmSize = _confirm.rect.size;
        _confirmScale = _confirm.localScale;
        //获取text对象
        _text = _confirm.GetChild(0).GetComponent<Text>();
        //获取text的大小
        _textSize = _text.GetComponent<RectTransform>().rect.size;
        _textScale = _text.rectTransform.localScale;
        //确定取消按钮
        _Confirm();
        _Cancel();
        //初始设置隐藏
        if (m_hideOnStart)
            _SetHideImmediate();
    }

    /// <summary>
    /// 无动画立即隐藏
    /// </summary>
    public void _SetHideImmediate()
    {
        //设置隐藏
        m_alert.gameObject.SetActive(false);
        _confirm.gameObject.SetActive(false);
        _text.gameObject.SetActive(false);
        _transparentMask.gameObject.SetActive(false);
        //宽高设置0
        m_alert.DOScale(Vector3.zero, 0);
        _confirm.DOScale(Vector3.zero, 0);
        //设置遮罩层alpha = 0
        _transparentMask.GetComponent<Image>().DOFade(0, 0);
    }
    /// <summary>
    /// 开始时为隐藏状态
    /// </summary>
    [Tooltip("开始时为隐藏状态")]
    public bool m_hideOnStart = true;
    /// <summary>
    /// 隐藏
    /// </summary>
    public void _SetHide()
    {
        //设置隐藏
        _text.gameObject.SetActive(false);
        //宽高设置0
        m_alert.DOScale(Vector2.zero, _SetShow_duration)
            .onComplete = () =>
            {
                m_alert.gameObject.SetActive(false);
            };
        _confirm.DOScale(Vector2.zero, _SetShow_duration)
            .onComplete = () =>
            {
                _confirm.gameObject.SetActive(false);
            };
        //隐藏透明遮罩层
        _transparentMask.GetComponent<Image>().DOFade(0, _SetShow_duration)
            .onComplete = () =>
            {
                _transparentMask.gameObject.SetActive(false);
            };
    }
    /// <summary>
    /// 显示
    /// </summary>
    public void _SetShow()
    {
        //设置显示
        m_alert.gameObject.SetActive(true);
        _confirm.gameObject.SetActive(true);
        _transparentMask.gameObject.SetActive(true);
        //宽高设置成初始大小+5%再回到原来的大小
        m_alert.DOScale(_uiBlurScale + _uiBlurScale * 0.05f, _SetShow_duration)
            .onComplete = () =>
            {
                //完成后回到初始大小 时间为原来的1/5
                m_alert.DOScale(_uiBlurScale, _SetShow_duration / 5f);
            };
        _confirm.DOScale(_confirmScale + _confirmScale * 0.05f, _SetShow_duration)
            .onComplete = () =>
            {
                //完成后回到初始大小 时间为原来的1/5
                _confirm.DOScale(_confirmScale, _SetShow_duration / 5f);
                //并且显示text
                _text.gameObject.SetActive(true);
            };
        //显示透明遮罩层
        _transparentMask.GetComponent<Image>().DOFade(_transparentMaskColor.a, _SetShow_duration);
    }
    /// <summary>
    /// 显示动画时间
    /// </summary>
    private float _SetShow_duration = 0.3f;

    /// <summary>
    /// 按钮的hover效果
    /// </summary>
    /// <param name="button">按钮</param>
    public void _OnHover(Transform button)
    {
        if (!m_inited)
        {
            m_inited = true;
            //获取初始大小
            m_initialScale = transform.GetComponent<RectTransform>().localScale.x;
        }
        if (!button.GetComponent<EventTrigger>()) button.gameObject.AddComponent<EventTrigger>();
        EventTrigger trigger = button.GetComponent<EventTrigger>();
        EventTrigger.Entry entry = new EventTrigger.Entry();
        entry.eventID = EventTriggerType.PointerEnter;
        entry.callback = new EventTrigger.TriggerEvent();
        entry.callback.AddListener(delegate (BaseEventData baseEvent) {
            button.GetComponent<RectTransform>().DOScale(m_localScale, 0.3f);
        });
        trigger.triggers.Add(entry);

        EventTrigger.Entry entry2 = new EventTrigger.Entry();
        entry2.eventID = EventTriggerType.PointerExit;
        entry2.callback = new EventTrigger.TriggerEvent();
        entry2.callback.AddListener(delegate (BaseEventData baseEvent) {
            button.GetComponent<RectTransform>().DOScale(m_initialScale, 0.3f);
        });
        trigger.triggers.Add(entry2);
    }
    /// <summary>
    /// 变大尺度默认1
    /// </summary>
    [Tooltip("变大尺度默认1.2f")]
    public float m_localScale = 1.2f;
    /// <summary>
    /// 初始的大小
    /// </summary>
    private float m_initialScale;
    /// <summary>
    /// 是否被初始化
    /// </summary>
    private bool m_inited = false;

    /// <summary>
    /// 确定
    /// </summary>
    public void _Confirm()
    {
        _OnHover(m_confirm);
        m_confirm.GetComponent<Button>().onClick.AddListener(delegate {
            _SetHide();
        });
    }
    /// <summary>
    /// 确定按钮
    /// </summary>
    [Tooltip("确定按钮")]
    public Transform m_confirm;
    /// <summary>
    /// 取消按钮
    /// </summary>
    public void _Cancel()
    {
        _OnHover(m_cancel);
        m_cancel.GetComponent<Button>().onClick.AddListener(delegate {
            _SetHide();
        });
    }
    [Tooltip("取消按钮")]
    public Transform m_cancel;

}

18.将Alert.cs脚本拖拽到Alert对象上,并分别将Confirm和Cancel对象拖拽到Alert对应的组件上

19.再在Assets>Scripts文件夹下新建键盘事件的脚本 KeyEvent.cs

20.KeyEvent.cs脚本内容

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

public class KeyEvent : MonoBehaviour
{
    /// <summary>
    /// 获取Alert组件
    /// </summary>
    private Alert alert;
    void Start()
    {
        //实例化组件
        alert = Alert.Instance;
    }

    void Update()
    {
        //键盘事件
        _KeyDown();
    }

    /// <summary>
    /// 按下键盘执行
    /// </summary>
    public void _KeyDown()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            alert._SetShow();
        }
    }

}

21.在Hierarchy下新建一个脚本管理器的空物体Script,并将KeyEvent.cs脚本附在其上

22.为了让Hierarchy下的组件的层次更加明显,分别新建了三个空物体,具体如下

23.最后运行游戏,按下Esc键弹出信息框

结束:GIF效果图请看文章顶部!

2017-05-14 20:14:32 jxw167 阅读数 2719

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

CSDN视频网址:http://edu.csdn.net/lecturer/144

在利用Unity3D引擎开发程序时,UI资源的加载,卸载,隐藏以及UI渐变动画等功能是UI架构设计必须考虑的。

做每一款游戏都需要将这些功能编写一遍非常耗时,在此给读者介绍一种快速的实现方式,因为我们这个是通用的

模块,所以必须要使用模板实现,而且我们的逻辑脚本是不挂接到对象上的。接下来首先设计一个管理类Manager,

代码如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
/// <summary>
/// 抽象管理类
/// </summary>
/// <typeparam name="K"></typeparam>
/// <typeparam name="V"></typeparam>
public class Manager<T,K, V> : Singleton<T>
    where V : class ,IDisposable
    where T : Singleton<T>, new()
{
    protected Dictionary<K, V> mMap = new Dictionary<K, V>();
 
    /// <summary>
    /// 获取 对应实体
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public V Get(K key)
    {
        if (key == null) return null;
        return mMap.ContainsKey(key) ? mMap[key] : null;
    }

    /// <summary>
    /// 获取类型T的 Value
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    public U Get<U>(K key) where U : class,V 
    {
        V v = Get(key);
        return v as U;
    }

    /// <summary>
    /// 获取类型T的Value
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T Get<T>() where T : class,V 
    {
        foreach(V value in mMap.Values)
        {
            if(value.GetType().Equals(typeof(T)))
            {
                return value as T;
            }
        }
        return null;
    }
    /// <summary>
    /// 添加对应实体
    /// </summary>
    /// <param name="key"></param>
    /// <param name="value"></param>
    public bool Put(K key, V value)
    {
        if (mMap.ContainsKey(key))
        {
            if (value == mMap[key])
            {
                return false;
            }
            V v = mMap[key];
            mMap[key] = value;
            v.Dispose();
        }
        else
        {
            mMap.Add(key, value);
        }
        return true;
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public bool Remove(K key)
    {
        if (mMap.ContainsKey(key))
        {
            V v = mMap[key];
            mMap.Remove(key);
            v.Dispose();
        }
        return true;
    }


    public Dictionary<K,V>.ValueCollection Values
    {
        get { return mMap.Values; }
    }
    /// <summary>
    /// 清除所有管理的对象
    /// </summary>
    public void Clear()
    {
        foreach (V value in mMap.Values)
        {
            value.Dispose();
        }
        mMap.Clear();
    }
}

public class ManagerT<K, V> : Manager<ManagerT<K,V>, K, V>
    where V : class ,IDisposable
{

}


在这个类属于抽象类,它利用Dictionary实现了对象的管理操作,接下来需要实现UI的管理类了,先把代码给读者展示如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

/// <summary>
/// UI 服务类
/// </summary>
public class UIService : Manager<UIService, string, UIService.UI>,IDisposable
{
    public void Dispose()
    {
        DestroyAll();
    }

    /// <summary>
    /// 创建UI
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    /// <returns></returns>
    private T _CreateUI<T>(string name) where T : UI
    {
        T ui = Activator.CreateInstance(typeof(T), name) as T;
        return ui;
    }

    public class UIHolder : MonoBehaviour
    {
        public UI ui { get; set; }
    }
    public class UI : IDisposable
    {
        public UI(string name)
        {
                _Init(name);  
        }

        public enum UIStyle
        {
            Normal,//默认类型
            HideByTapScene,//点击空白处隐藏类型,和黑底不冲突
        }

        UIStyle mStyle = UIStyle.Normal;

        public UIStyle Style
        {
            get { return mStyle; }
            set { mStyle = value; }
        }

        internal GameObject mPrefab = null;
        protected UIPanel mPanel = null;
        #region 面板动画处理
        protected UITweener[] mTweens = null;
        protected UITweener   mMainTween = null;
        protected UITweener.ToggleStyle mMainToggleStyle = UITweener.ToggleStyle.normal;
        private void _TweensInit()
        {
            mTweens = mPrefab.GetComponentsInChildren<UITweener>();
            if (mTweens != null)
            {
                UITweener tween;
                for (int i = 0; i < mTweens.Length; ++i)
                {
                    tween = mTweens[i];
                    if (tween.toggleStyle == UITweener.ToggleStyle.OnShow)
                    {
                        mMainTween = tween;
                        mMainToggleStyle = UITweener.ToggleStyle.OnShow;
                    }
                    if (tween.toggleStyle == UITweener.ToggleStyle.OnShowAndHide)
                    {
                        mMainTween = tween;
                        mMainToggleStyle = UITweener.ToggleStyle.OnShowAndHide;
                        break;
                    }
                }
            }
        }

        private bool _HasTween()
        {
            return mMainTween != null && mMainTween.toggleStyle !=  UITweener.ToggleStyle.normal;
        }
        private void _TweenOnShow(EventDelegate.Callback call)
        {
            mMainTween.SetOnFinished(call);
            UITweener tween;
            for (int i = 0; i < mTweens.Length; ++i)
            {
                tween = mTweens[i];
                if(tween.toggleStyle != UITweener.ToggleStyle.normal)
                {
                    tween.ResetToStart(true);
                    tween.PlayForward();
                }
            }
        }

        private void _TweenOnHide(EventDelegate.Callback call)
        {
            if (mMainToggleStyle == UITweener.ToggleStyle.OnShow)
            {
                call();
                return;
            }
            mMainTween.SetOnFinished(call);
            UITweener tween;
            for (int i = 0; i < mTweens.Length; ++i)
            {
                tween = mTweens[i];
                if (tween.toggleStyle == UITweener.ToggleStyle.OnShowAndHide)
                {
                    tween.ResetToStart(!true);
                    tween.PlayReverse();
                }
            }
        }
        private void _Dummy()
        {

        }
        private void _Hide()
        {
            mPrefab.SetActive(false);
            mHiding = false;
        }
        #endregion

        internal void _Init(string name)
        {
            try
            {
                GameObject prefab = Resource.LoadUI(name);
                mPrefab = GameObject.Instantiate(prefab) as GameObject;
                UIHolder uiholder = UtilGameObject.GetOrAddComponent<UIHolder>(mPrefab);
                uiholder.ui = this;
                mPrefab.name = name;
                mPanel = mPrefab.GetComponent<UIPanel>(); //允许Panel为空
                _TweensInit();
            }
            catch (Exception e)
            {
                Looper.LogException(e);
            }
            UIService.Instance.InitUI(mPrefab);
            UIService.Instance._OnShowUI(this, true);
        }
        #region <默认属性>
 
        
        /// <summary>
        /// 深度信息
        /// </summary>
        public int depth
        {
            get
            {
                if (mPanel==null)
                {
                    return -1;
                }
                return mPanel.depth;
            }
            set
            {
                if (mPanel == null) return;
                mPanel.depth = value;
            }
        }
        /// <summary>
        /// 是否正在显示
        /// </summary>
        /// <returns></returns>
        public bool IsShowing()
        {
            if (mPrefab == null)
                return false;
            return mPrefab.activeSelf;
        }
        float mLastShowTime = Time.time;
        /// <summary>
        /// 最后一次显示的时间
        /// </summary>
        public float LastShowTime
        {
            get { return mLastShowTime; }
            set { mLastShowTime = value; }
        }
        #endregion

        /// <summary>
        /// 名字(和预制件名称一样)
        /// </summary>
        public  string Name
        {
            get { return mPrefab != null ? mPrefab.name : ""; }
        }
        /// <summary>
        /// 销毁对象
        /// </summary>
        public void Dispose()
        {
            UIService.Instance._OnHidUI(this);

            try
            {
                OnClose();
                if (mPrefab != null)
                {
                    GameObject.DestroyImmediate(mPrefab);
                    mPrefab = null;
                }

            }
            catch (Exception e)
            {
                Looper.LogException(e);
            }
            
        }

        /// <summary>
        /// 刷新界面
        /// 1 Grid 重排问题
        /// </summary>
        public void Refresh()
        {
           
                UIGrid[] grids = mPrefab.GetComponentsInChildren<UIGrid>();
                foreach (UIGrid grid in grids)
                {
                    if (grid != null && !grid.animateSmoothly)
                    {
                        grid.Reposition();
                    }
                }
           
        }


        public IEnumerator _Refresh()
        {
            {
                UIGrid[] grids = mPrefab.GetComponentsInChildren<UIGrid>();
                foreach (UIGrid grid in grids)
                {
                    if (grid != null && !grid.enabled)
                    {
                        grid.repositionNow = true;
                        grid.Reposition();
                    }
                }
            }

            yield return null;
        }


        //解决同一个UI动画隐藏还没结束,动画显示就开始了 状态不对的问题
        bool mHiding = false;
        /// <summary>
        /// 是否显示
        /// </summary>
        public void Show(bool v)
        {

            if (v)
            {
                if (mHiding)
                {
                    _Hide();
                }
                UIService.Instance._OnShowUI(this);
            }
            else
            {
                UIService.Instance._OnHidUI(this);
            }

            try
            {

                if (mPrefab != null)
                {
                    
                    if (_HasTween())
                    {
                        if (v)
                        {
                            mPrefab.SetActive(true);
                            _TweenOnShow(_Dummy);
                        }
                        else
                        {
                            mHiding = true;
                            _TweenOnHide(_Hide);
                        }
                    }
                    else
                    {
                        mPrefab.SetActive(v);
                    }
                    OnShow(v);
                    if (v)
                    {
                        LastShowTime = Time.time;
                        Refresh();
                        //();
                    }
                }
                
            }
            catch (Exception e)
            {
                Looper.LogException(e);
            }


        }


        /// <summary>
        /// 跟随场景中物体
        /// </summary>
        /// <param name="target"></param>
        public void ApplyHub(Transform target)
        {
            NGUIExt guiExt = PluginManager.Instance.Get<NGUIExt>();
            if (guiExt != null)
            {
                guiExt.ApplyHud(mPrefab, target);
            }
        }

        public virtual void OnCreate() { }
        public virtual void OnShow(bool v) { }
        public virtual void OnClose() { }

        /// <summary>
        /// 点击事件
        /// </summary>
        /// <param name="obj">被点击的控件</param>
        public virtual void OnClick(GameObject obj) { }

        /// <summary>
        /// 双击事件
        /// </summary>
        /// <param name="obj">被双击的控件</param>
        public virtual void OnDoubleClick(GameObject obj) { }
        /// <summary>
        /// 按住事件
        /// </summary>
        /// <param name="obj">被Pressed的控件</param>
        /// <param name="pressed"></param>
        public virtual void OnPress(GameObject obj, bool isPressed) { }

        /// <summary>
        /// 拖动事件
        /// </summary>
        /// <param name="obj">拖动的控件</param>
        /// <param name="delta"></param>
        public virtual void OnDrag(GameObject obj, Vector2 delta) { }

        /// <summary>
        /// 拖放事件
        /// </summary>
        /// <param name="obj">拖放的当前控件</param>
        /// <param name="objSelected">一直被拖住的控件</param>
        public virtual void OnDrap(GameObject obj, GameObject objSelected) { }

        /// <summary>
        /// 显示Tooltip事件
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="isShow">显示或隐藏Tooltip</param>
        public virtual void OnTooltip(GameObject obj, bool isShow) { }

        /// <summary>
        /// 被选中事件
        /// </summary>
        /// <param name="obj">被选中的控件</param>
        /// <param name="isSelected">选中或取消被选中</param>
        public virtual void OnSelect(GameObject obj, bool isSelected) { }

        /// <summary>
        /// 光标划过事件
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="isHover">光标进入或光标离开</param>
        public virtual void OnHover(GameObject obj, bool isHover) { }

        /// <summary>
        /// 根据类型获取对应名称控件;
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <returns></returns>
        protected T GetChild<T>(string name,GameObject obj = null, int index = 0) where T : MonoBehaviour
        {
            if(obj == null)
            {
                obj = mPrefab;
            }

            Transform child = obj.transform.Find(name);
            if (child == null)
            {
                T[] childs = obj.GetComponentsInChildren<T>();
                foreach (T t in childs)
                {
                    if (t.gameObject.name == name)
                    {
                        return t;
                    }
                }
            }
            else
            {
                if (child.childCount == 0)
                {
                    return child.GetComponent<T>();
                }

                {
                    int count = 0;
                    T[] comps = child.GetComponents<T>();
                    foreach (T t in comps)
                    {

                        if (t.gameObject.name == name && count == index)
                        {
                            return t;
                        }
                        count++;
                    }
                }
                {
                    int count = 0;
                    T[] childs = child.GetComponentsInChildren<T>();
                    foreach (T t in childs)
                    {

                        if (t.gameObject.name == name && count == index)
                        {
                            return t;
                        }
                        count++;
                    }
                }

            }

            Debug.LogError(obj.name + " hasn't Components :" + typeof(T).Name + " in children named:" + name);
            return null;
        }

        protected GameObject FindChild(string name)
        {
            var child = mPrefab.transform.FindChild(name);
            return child.gameObject;
        }

        protected T FindChild<T>(string name) where T : Component
        {
            var child = mPrefab.transform.FindChild(name);
            T cmp = child.GetComponent<T>();
        
            return cmp;
        }

        /// <summary>
        /// 获取对应名称子控件;
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        protected GameObject GetChild(string name, GameObject obj = null)
        {
            if(obj == null)
            {
                obj = mPrefab;
            }
            Transform child = obj.transform.Find(name);
            if (child == null)
            {
                Debug.LogError(obj.name + "is not find child of:" + name);
                return null;
            }
            return child.gameObject;
        }
        /// <summary>
        /// 用指定的对象替换子对象
        /// </summary>
        /// <param name="name">子对象名字</param>
        /// <param name="obj">指定的对象</param>
        /// <returns></returns>
        protected bool ReplaceChild(string name, GameObject obj)
        {
            GameObject orginal = GetChild(name);

            if (orginal == null) {
				GameObject.DestroyImmediate (obj);
				return false;
			}
            obj.transform.parent = orginal.transform.parent;
            obj.transform.localPosition = Vector3.zero;
            obj.transform.localRotation = Quaternion.identity;
            obj.transform.localScale = Vector3.one;
			obj.name = orginal.name;

			orginal.transform.parent = null;
			GameObject.DestroyImmediate (orginal);

            return true;
        }

        /// <summary>
        /// 用指定的对象替换子对象
        /// </summary>
        /// <param name="orginal">原件</param>
        /// <param name="obj">指定的对象</param>
        /// <returns></returns>
        protected bool ReplaceChild(GameObject orginal, GameObject obj)
        {
            if (orginal == null) {
				GameObject.DestroyImmediate (obj);
				return false;
			}
            obj.transform.parent = orginal.transform.parent;
            obj.transform.localPosition = Vector3.zero;
            obj.transform.localRotation = Quaternion.identity;
            obj.transform.localScale = Vector3.one;
			obj.name = orginal.name;

			orginal.transform.parent = null;
			GameObject.DestroyImmediate (orginal);
            return true;
        }

    }


    NGUIExt mPlugin;
    GameObject mBG;
    UIPanel mBGPanel;
    int mBGCount = 0;

    private void _OnShowUI(UI t,bool init = false)
    {
        if (t.IsShowing())
        {
            if(!init)
                return;
        }
        if (t.IsShowBlackBG())
        {
            mBGCount++;
            if (mBGCount > 0 && mBG.activeSelf == false)
            {
                mBG.SetActive(true);
            }
            if (mBG.activeSelf)
            {
                mBGPanel.depth = t.depth-1;
            }
        }

    }
    private void _OnHidUI(UI t)
    {
        if (!t.IsShowing()) return;

        if (t.IsShowing() && t.IsShowBlackBG())
        {
            mBGCount--;
            if(mBGCount <= 0)
            {
                mBGCount = 0;
                if (mBG.activeSelf == true)
                {
                    mBG.SetActive(false);
                }
            }


            if (mBG.activeSelf)
            {
                UI ui = _GetLastShowUI(true, t);
                if (ui != null) mBGPanel.depth = ui.depth-1;
            }
        }

    }

    public bool IsFingerHoverGUI()
    {
        if(mPlugin == null)
        {
            return false;
        }
        return mPlugin.IsFingerHoverGUI;
    }

    public bool IsFingerHoverGUI3D()
    {
        if (mPlugin == null)
        {
            return false;
        }
        return mPlugin.IsFingerHoverGUI3D();
    }

    public bool IsFingerHoverGUIWithout3D()
    {
        if (mPlugin == null)
        {
            return false;
        }
        return mPlugin.IsFingerHoverGUIWithout3D();
    }

    public bool IsPrefab(GameObject ui_prefab)
    {
        return mPlugin.IsPrefab(ui_prefab);
    }
    
    /// <summary>
    /// 初始化 继承与 Singleton 对象构建的时候被调用
    /// </summary>
    protected override void OnCreate()
    {
        
        mPlugin = PluginManager.Instance.Get<NGUIExt>();
        if (mPlugin != null)
        {
            mPlugin.SetEventHandler(this._HandlerUIEvent);
        }
        GameObject prefab = Resource.LoadUICommon("black_background");
        Looper.Assert(prefab != null , "默认黑底 black_background Prefab不存在 !!");
        if(prefab != null)
        {
            mBG = mPlugin.AddChild(prefab);
            mBGPanel = mBG.GetComponent<UIPanel>();
            mBG.transform.localScale = new Vector3(1, 1, 1);
            mBG.transform.localPosition = new Vector3(mBG.transform.localPosition.x, mBG.transform.localPosition.y, Mathf.Clamp(mBG.transform.localPosition.z, -2f, 2f));
            if(mBG != null)
            {
                UISprite sprite = mBG.GetComponent<UISprite>();
                BoxCollider collider = mBG.GetComponent<BoxCollider>();
                if(sprite!= null)
                {
                    Vector2 size = mPlugin.GetSize();
                    sprite.SetDimensions((int)size.x, (int)size.y);
                    collider.size = new Vector3(size.x, size.y, 0);
                }
            }
            
            mBG.SetActive(false);
        }
        //EasyTouch.On_SimpleTap += On_SimpleTap;
        
    }

    public void InitUI(GameObject ui)
    {
        try
        {
            LayerUtils.SetLayer(ui.transform, (int)LayerUtils.ELayerIndex.ui);
            ui.transform.parent = mPlugin.GetRoot().transform;
            
            switch(ui.name)
            {
                default:
                    ui.transform.localScale = new Vector3(1, 1, 1);
                    ui.transform.localPosition = Vector3.zero;
                    break;
            }
        }
        catch (Exception e)
        {
            Looper.LogException(e);
        }
      
    }
    /// <summary>
    /// 创建UI
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    /// <returns></returns>
    public T CreateUI<T>(string name) where T: UI
    {
        UI  t = this.Get(name) as T;
        if(t == null)
        {
            t = _CreateUI<T>(name) as UI;
           try
           {
               t.OnCreate();
           }
           catch (Exception e)
           {
               Looper.LogException(e);
           }
           
           Put(name, t);
        }
        return t as T;
    }
    List<UI> mUIScene = new List<UI>();
    /// <summary>
    /// 创建一个不加入管理队列的UI,主要用于世界地图上关卡界面的创建。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    /// <returns></returns>
    public T CreateUIWithoutManager<T>(string name) where T : UI
    {
        T ui = _CreateUI<T>(name);
        try
        {
            ui.OnCreate();
        }
        catch (Exception e)
        {
            Looper.LogException(e);
        }
        mUIScene.Add(ui);
        return ui;
    }
	
    /// <summary>
    /// 销毁不加入队列的UI
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="ui"></param>
    public void CloseUIWithoutManager<T>(T ui) where T : UI
    {
        try
        {
            ui.OnClose();
            ui.Dispose();
        }
        catch (Exception e)
        {
            Looper.LogException(e);
        }
        mUIScene.Remove(ui);
    }
    /// <summary>
    /// 显示UI
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    public T ShowUI<T>(string name) where T : UI
    {
        T t = CreateUI<T>(name);
        if(t != null)
        {
            t.Show(true);
        }
        return t;
    }
    /// <summary>
    /// 显示UI
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    public T HideUI<T>(string name) where T : UI
    {
        T t = Get<T>(name);
        if (t != null)
        {
            t.Show(!true);

        }
        return t;
    }

    Stack<UI> mStack = new Stack<UI>();

    /// <summary>
    /// 清除栈
    /// </summary>
    public void StackClean()
    {
        mStack.Clear();
    }
    /// <summary>
    /// UI隐藏压栈
    /// </summary>
    /// <param name="t"></param>
    /// <returns></returns>
    public UI Push(UI t)
    {
        if (t != null)
        {
            t.Show(false);
            mStack.Push(t);
        }
        return t;
    }
    /// <summary>
    /// UI隐藏压栈
    /// </summary>
    /// <param name="t"></param>
    /// <returns></returns>
    public T Push<T>(string name) where T: UI
    {
        T t = Get<T>(name);
        if (t != null)
        {
            t.Show(false);
            mStack.Push(t);
        }
        return t;
    }
    /// <summary>
    /// UI显示出栈
    /// </summary>
    /// <param name="t"></param>
    /// <returns></returns>
    public UI Pop()
    {
        UI t = mStack.Pop();
        if (t != null)
        {
            t.Show(true);
        }
        return t;
    }


    /// <summary>
    /// 销毁UI
    /// </summary>
    /// <param name="name"></param>
    public void Distroy(string name)
    {
        UI ui = Get(name);
        if(ui != null)
        {
            ui.Dispose();
            Remove(name);
        }
    }

    public void Distroy<T>(string name) where T : UI
    {
        UI ui = Get<T>(name);
        if (ui != null)
        {
            ui.Dispose();
            Remove(name);
        }
    }
    public void DestroyAll(bool includeScene= false)
    {
        StackClean();
        Clear();
        if(includeScene)
        {
            foreach (UI ui in mUIScene)
            {
                ui.Dispose();
            }
            mUIScene.Clear();
        }

    }
    /// <summary>
    /// 隐藏其他UI
    /// </summary>
    /// <param name="name"></param>
    public void HideOtherUI(string name)
    {
        foreach (UI ui in Values)
        {
            if (ui.Name.Equals(name))
                continue;
            ui.Show(false);
        }
    }

    UI _GetLastShowUI(bool showBG = false,UI except=null)
    {
        UI lastShowUI = null;
        float lastShowTime = 0;
        foreach (UI ui in Values)
        {
            if (ui == except) continue;
            if (ui.IsShowing() && ui.LastShowTime > lastShowTime)
            {
                if (showBG)
                {
                    if (ui.IsShowBlackBG())
                    {
                        lastShowUI = ui;
                        lastShowTime = ui.LastShowTime;
                    }
                }else
                {
                    lastShowUI = ui;
                    lastShowTime = ui.LastShowTime;
                }
            }
        }
        return lastShowUI;
    }

    /// <summary>
    /// 隐藏最新显示的UI
    /// </summary>
    public void HideLastShow()
    {
        UI lastShowUI = _GetLastShowUI();
        if (lastShowUI != null)
        {
            lastShowUI.Show(false);
        }
    }
    /// <summary>
    /// 隐藏所有UI
    /// </summary>
    public void HideAllUI()
    {
        foreach(UI ui in Values)
        {
            if(ui != null)ui.Show(false);
        }
    }
    /// <summary>
    /// 获取UI跟面板
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
     GameObject _GetRootPanelExt(GameObject obj)
    {
        Transform parent = obj.transform.parent;
        UIHolder uiHolder = null;// = root.GetComponent<UIService.UIHolder>();

        while (parent != null)
        {
            if (parent.gameObject.GetComponent<UICamera>() != null)
                break;

            UIHolder tempPanel = parent.GetComponent<UIHolder>();
            if (tempPanel != null)
            {
                uiHolder = tempPanel;
            }
            parent = parent.parent;
        }
        if (uiHolder == null)
        {
            return null;
        }
        return uiHolder.gameObject;
    }
    /// <summary>
    /// NGUI事件处理器
    /// </summary>
    /// <param name="eventNane">事件名称</param>
    /// <param name="sender">发送事件的控件</param>
    /// <param name="arg">事件参数</param>
    private void _HandlerUIEvent(string eventName, GameObject sender, object arg)
    {
        try
        {
            if(sender == mBG)
            {
                //MainLooper.LogError("mBG, eventName:" + eventName + "!!");
                if (eventName.Equals("OnClick"))
                {
                   
                }
                return;
            }
            GameObject root = _GetRootPanelExt(sender);//mPlugin.GetRootPanel(sender);
            if (root == null) return;
            UI ui = Get(root.name);
            if(ui == null)
            {
                UIHolder uiHolder = root.GetComponent<UIHolder>();
                if( uiHolder!= null) ui = uiHolder.ui;
            }
            if (ui == null)
            {
                Debug.LogWarning("UI:" + root.name + " not match prefab's name " + sender.name);
                return;
            }

            if (eventName.Equals("OnClick"))
            {
                ui.OnClick(sender);
            }
            else if (eventName.Equals("OnPress"))
            {
                ui.OnPress(sender, (bool)arg);
            }
            else if (eventName.Equals("OnDrag"))
            {
                ui.OnDrag(sender, (Vector2)arg);
            }
            else if (eventName.Equals("OnDrop"))
            {
                ui.OnDrap(sender, (GameObject)arg);
            }
            else if (eventName.Equals("OnSelect"))
            {
                ui.OnSelect(sender, (bool)arg);
            }
            else if (eventName.Equals("OnHover"))
            {
                ui.OnHover(sender, (bool)arg);
            }
            else if (eventName.Equals("OnTooltip"))
            {
                ui.OnTooltip(sender, (bool)arg);
            }
            else if (eventName.Equals("OnDoubleClick"))
            {
                ui.OnDoubleClick(sender);
            }
        }
        catch(Exception e)
        {
            Looper.LogException(e);
        }

    }
}

该类实现了UI的创建,也就是我们说的实例化操作,以及UI的显示,隐藏,动画等效果。在代码的最后使用了点击的回调函数避免

将脚本挂接到对象上。以上类的实现基本上把UI的大部分功能都实现出来了,可以直接拿过来使用。


2018-03-21 15:34:04 wxblzzz 阅读数 339
Unity3D的UI系统(UGUI)初级入门—288人已学习
课程介绍    
jpg
    本课程主要介绍Unity3d的UI系统(UGUI),先对UGUI做一个总体概述,之后对每个UI控件逐一进行详细讲述,内容包括控件的作用、设置方法、使用场景及属性细节,帮助大家熟练使用UGUI设计游戏的交互界面。
课程收益
    在游戏开发中,UI系统是必不可少的一个组成部分,但大部分同学对Unity3d的UI系统的了解都比较零散,没有条理,本课程旨在帮助大家系统的梳理Unity3d的UI系统,使大家对UGUI有更全面更详细的了解。
讲师介绍
    伍晓波更多讲师课程
    6年程序开发经验,精通C/C++/C#编程。 曾担任过Unity3d游戏开发主程和Unity3d游戏开发讲师,熟悉Unity3d的UI系统、物理引擎、动画系统、粒子系统等,对小型、中型游戏有丰富的项目经验,益智类、敏捷类、塔防、RPG均有广泛涉猎。
课程大纲
  第1章:UGUI概述和Canvas(画布)组件
    1.UGUI概述和Canvas(画布)组件  15:31
  第2章:Image(图片)组件的基本属性
    1.RectTransform组件和Image组件的基本配置  21:47
    2.Image组件Tiled(堆叠)和Sliced(切割)模式的使用  12:12
    3.Image组件Filled(填充)模式和技能冷却效果的代码实现  18:15
  第3章:Text(文本)组件的基本属性
    1.Text(文本)组件的基本配置和富文本编辑  20:38
    2.Text(文本)组件的脚本控制和计时器的实现  22:24
  第4章:Button(按钮)组件的基本属性
    1.Button(按钮)组件的基本结构和ColorTint设置  15:52
    2.Button(按钮)组件的图片过渡效果和动画过渡效果  11:20
    3.Button(按钮)组件的UI导航功能(Navigation)  11:51
    4.Button(按钮)组件的点击事件(上)  13:03
    5.Button(按钮)组件的点击事件(下)  15:33
  第5章:Toggle(开关)组件的基本属性
    1.Toggle(开关)组件的基本结构和事件触发  20:27
    2.ToggleGroup组件的使用方法  15:39
  第6章:Slider(滑动栏)组件的基本属性
    1.Slider(滑动栏)组件的基本属性  45:16
  第7章:ScrollBar(滚动条)组件的基本属性
    1.ScrollBar(滚动条)组件的基本结构和属性界面  16:29
    2.ScrollRect组件实现滚动视图  26:41
    3.ScrollRect组件的事件触发  7:27
  第8章:DropDown(下拉栏)组件的基本属性
    1.DropDown(下拉栏)组件的基本结构和属性界面  17:24
    2.DropDown(下拉栏)组件的脚本配置方法  21:45
    3.图片类型下拉栏(DropDown)的实现  23:32
  第9章:InputField(文本输入框)组件的基本属性
    1.InputField(文本输入框)组件的基本结构和属性界面  18:23
    2.InputField(文本输入框)组件的脚本配置方法和事件触发  23:05
  第10章:EventTrigger(事件触发器)组件的基本属性
    1.在Inspector界面添加EventTrigger(事件触发器)的鼠标事件(一)  17:35
    2.在Inspector界面添加EventTrigger(事件触发器)的鼠标事件(二)  11:22
    3.在脚本中通过接口方式添加EventTrigger(事件触发器)的鼠标事件  15:51
  第11章:屏幕适配
    1.CanvasScaler组件和屏幕适配(一)  20:46
    2.CanvasScaler组件和屏幕适配(二)  11:22
  第12章:UGUI中UI控件的遮挡关系
    1.Overlay模式画布中UI控件的遮挡关系  13:35
    2.Camera模式画布中UI控件的遮挡关系  11:35
    3.WorldSpace模式画布中UI控件的遮挡关系  12:53
大家可以点击【查看详情】查看我的课程
2018-01-31 19:41:19 YuAnHandSome 阅读数 1474

Unity UI EventTrigger 动态添加UI事件

UI中点击、按下、抬起、进入、退出、拖拽等事件,可以引用各自的接口,实现接口中的方法来完成相应需求。但是如果一个对象身上要完成很多事件,引用大量接口就显得麻烦了。为了避免引用借口过多,实现动态绑定事件可以用EventTrigger组件来完成。下面给大家演示一下EventTrigger组件的使用方法,以及如何在代码里动态添加所需的事件。

EventTrigger的在Inspector中使用

EventTrigger在Inspector面板的属性:在代码中写好对应事件的方法,选出要添加Event Type,像Button一样把方法拖拽到对应的EventType上即可,如下图:

EventTrigger的在带代码动态绑定事件使用

代码中动态创建要有以下几个步骤:
1、实例化所有委托的列表
2、新建所需的事件
3、注册eventID
4、新建callback
5、设置对应事件的内容
6、绑定事件
7、把事件添加到委托列表

以上7步是EventTrigger动态添加事件的步骤,按照步骤来就很容易了。
下面是演示效果

EventTrigger用好动态添加事件,会很方便,省去很多接口,随便一个UI控件加上EventTrigger组件后,所有的交互都可以很容易的完成。下面附上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// using namespace
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;

public class EventTriggerTest : MonoBehaviour {

    Text testT;
    EventTrigger testET;
    private void Start()
    {
        testT = transform.Find("Text").GetComponent<Text>();
        
        testET = gameObject.GetComponent<EventTrigger>();
        if (testET == null)
            testET = gameObject.AddComponent<EventTrigger>();

        // 实例化委托列表
        testET.triggers = new List<EventTrigger.Entry>();

        // 注册事件
        EventTrigger.Entry entryPointerEnter = new EventTrigger.Entry();
        EventTrigger.Entry entryPointerExit = new EventTrigger.Entry();
        EventTrigger.Entry entryPointerDown = new EventTrigger.Entry();
        EventTrigger.Entry entryPointerUp = new EventTrigger.Entry();
        EventTrigger.Entry entryDrag = new EventTrigger.Entry();

        // 实例化eventID
        entryPointerEnter.eventID = EventTriggerType.PointerEnter;
        entryPointerExit.eventID = EventTriggerType.PointerExit;
        entryPointerDown.eventID = EventTriggerType.PointerDown;
        entryPointerUp.eventID = EventTriggerType.PointerUp;
        entryDrag.eventID = EventTriggerType.Drag;

        // 实例化callback
        entryPointerEnter.callback = new EventTrigger.TriggerEvent();
        entryPointerExit.callback = new EventTrigger.TriggerEvent();
        entryPointerDown.callback = new EventTrigger.TriggerEvent();
        entryPointerUp.callback = new EventTrigger.TriggerEvent();
        entryDrag.callback = new EventTrigger.TriggerEvent();

        // 设置事件
        UnityAction<BaseEventData> pointerEnterCB = new UnityAction<BaseEventData>(OnPointerEnterCBTarget);
        UnityAction<BaseEventData> pointerExitCB = new UnityAction<BaseEventData>(OnPointerExitCBTarget);
        UnityAction<BaseEventData> pointerDownCB = new UnityAction<BaseEventData>(OnPointerDownCBTarget);
        UnityAction<BaseEventData> pointerUpCB = new UnityAction<BaseEventData>(OnPointerUpCBTarget);
        UnityAction<BaseEventData> DragCB = new UnityAction<BaseEventData>(OnDragCBTarget);

        // 绑定事件
        entryPointerEnter.callback.AddListener(pointerEnterCB);
        entryPointerExit.callback.AddListener(pointerExitCB);
        entryPointerDown.callback.AddListener(pointerDownCB);
        entryPointerUp.callback.AddListener(pointerUpCB);
        entryDrag.callback.AddListener(DragCB);

        // 添加到委托列表
        testET.triggers.Add(entryPointerEnter);
        testET.triggers.Add(entryPointerExit);
        testET.triggers.Add(entryPointerDown);
        testET.triggers.Add(entryPointerUp);
        testET.triggers.Add(entryDrag);
    }
    // 进入 要做的事
    void OnPointerEnterCBTarget(BaseEventData baseEventData)
    {
        testT.text = "PointerEnter";
        Debug.Log("write here when PointerDown");
    }
    // 离开 要做的事
    void OnPointerExitCBTarget(BaseEventData baseEventData)
    {
        testT.text = "PointerExit";
        Debug.Log("write here when PointerExit");
    }
    // 按下 要做的事
    void OnPointerDownCBTarget(BaseEventData baseEventData)
    {
        testT.text = "PointerDown";
        Debug.Log("write here when PointerDown");
    }
    // 抬起 要做的事
    void OnPointerUpCBTarget(BaseEventData baseEventData)
    {
        testT.text = "PointerUp";
        Debug.Log("write here when PointerUp");
    }
    // 点击 要做的事
    void OnDragCBTarget(BaseEventData baseEventData)
    {
        transform.position = Input.mousePosition;
        testT.text = "Drag:" + Input.mousePosition;
        Debug.Log("write here when PointerClick");
    }
}

其他

更多Blog请见:https://yiyuan1130.github.io/
Github地址:https://github.com/yiyuan1130

2016-03-02 10:14:25 honey199396 阅读数 4329

Unity3D – 简单的UI管理结构

使用Unity3D做一些小游戏原型的时候,虽然我们想做UI,但是又没有美术的支持,我们使用一个简单的UI模板,所有不需要做UI的小游戏直接使用就行了,也不必要每次都要自己写。

首先写一个UIBase类,所有的UI类都继承这个类就可以了 。

代码块

UIBase类

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using DG.Tweening;
/// <summary>
/// UI控制器基类
/// </summary>
public abstract class UIBase : MonoBehaviour
{
    private Transform m_Transform;
    //UI是否已经显示
    [HideInInspector]
    public bool m_SelfShowed = false;
    // UI是否被初始化
    private bool m_Inited = false;
    private Vector3 m_DefaultPos = Vector3.zero;
    private CanvasGroup m_CanvasGroup;
    void Awake()
    {
        m_Transform = transform;
        m_DefaultPos = m_Transform.position;
    }
    void Start () {
        InitSuper ();
    }
    public void InitSuper()
    {
        if (m_Inited)
            return;
        m_Inited = true;
        m_CanvasGroup = GetComponent<CanvasGroup> ();
        if(m_CanvasGroup == null){
            gameObject.AddComponent<CanvasGroup> ();
            m_CanvasGroup = GetComponent<CanvasGroup> ();
            m_CanvasGroup.alpha = 1;
            m_CanvasGroup.ignoreParentGroups = false;
            m_CanvasGroup.interactable = false;
            m_CanvasGroup.blocksRaycasts = false;
        }
        gameObject.SetActive (true);
        Button[] buttons = GetComponentsInChildren<Button> ();
        foreach (var item in buttons) {
            Button btn = item as Button;
            btn.onClick.AddListener (delegate {
                this.DidOnClick (btn.gameObject);
            });
        }
        DidInitUI ();
    }
    public void ShowUI()
    {
        if (!m_SelfShowed) {
            InitSuper ();
            DidShowUI ();
        }
    }
    public void HideUI()
    {
        if (m_SelfShowed) {
            InitSuper ();
            DidHideUI ();
        }
    }
    public void OpenActivity()
    {
        m_SelfShowed = true;
        gameObject.SetActive (true);
        m_Transform.position = m_DefaultPos + new Vector3 (Screen.width, 0, 0);
        m_Transform.DOMoveX (m_DefaultPos.x, 0.2f);
    }
    public void CloseActivity ()
    {
        m_SelfShowed = false;
        float outPos = m_Transform.position.x - Screen.width;
        m_Transform.DOMoveX (outPos, 0.2f).OnComplete (delegate {
            gameObject.SetActive(false);
        });
    }
    /// <summary>
    /// 在Start中初始化UI的操作
    /// </summary>
    public abstract void DidInitUI ();
    /// <summary>
    /// 执行显示UI的操作
    /// </summary>
    public abstract void DidShowUI ();
    /// <summary>
    /// 执行关闭UI的操作
    /// </summary>
    public abstract void DidHideUI ();
    /// <summary>
    /// 注册按钮点击事件
    /// </summary>
    /// <param name="sender">Sender.</param>
    public abstract void DidOnClick (GameObject sender);
}

所有继承UIBase的类只需要实现几个抽象方法就可以了,ShowUI和HideUI的具体实现都放到了DidShowUI()和DidHideUI()里面,基类还用了DoTween来实现一个简单的打开UI,关闭UI的动画。

假如我们要做一个只有一个开始游戏按钮的主界面

新建一个类:MenuUI实现如下:

代码块

UIBase类

using UnityEngine;
using System.Collections;
public class MenuUI : UIBase {
    public override void DidInitUI (){ }
    public override void DidShowUI ()
    {
        OpenActivity ();
    }
    public override void DidHideUI ()
    {
        CloseActivity ();
    }
    public override void DidOnClick (GameObject sender)
    {
        switch (sender.name) {
        case "ButtonStart":
            GameManager.Instance.GameStart ();
            break;
        default:
            break;
        }
    }
}

点击按钮开始游戏。
其他相应的UI也可以使用这种方法。

下面是UI管理类,让你建立简单的UI不需要做任何操作就可以运行游戏了。

新建一个叫UIManager的类
实现如下:

代码块

using UnityEngine;
using System.Collections;
using MicroGame;
using System.Collections.Generic;
public class UIManager : Singleton<UIManager> {
    /// <summary>
    /// UI信息
    /// </summary>
    [System.Serializable]
    public struct UIInfo
    {
        public UIType type;
        public UIBase ui;
    }
    /// <summary>
    /// UI类型
    /// </summary>
    public enum UIType
    {
        _NONE,
        _MENU,          // 进入游戏主界面
        _GAMEOVER,      // 游戏结束界面
        _INGAME,        // 答题界面
        _CHOOSELEVEL    // 选关界面
    }
    // 所有UI信息
    [SerializeField]
    private UIInfo[] m_UIInfo;
    // 保存已经显示的UI
    [SerializeField]
    private Stack<UIBase> m_UIStack;
    // 当前UI类型
    private UIType m_CurrentType = UIType._NONE;
    // 即将打开UI的类型
    private UIType m_NextType = UIType._NONE;
    void Start () {
        InitUI ();
    }
    #region private funcs
    // 初始化所有UI
    void InitUI()
    {
        foreach (var item in m_UIInfo) {
            if (item.type == UIType._MENU) {
                ShowUI (item.type);
            } else {
                item.ui.gameObject.SetActive (false);
            }
        }
    }
    // 根据UI类型获取UI实例
    UIBase GetUI(UIType type)
    {
        foreach (var item in m_UIInfo) {
            if (item.type == type)
                return item.ui;
        }
        return null;
    }
    // 根据UI实例获取UI类型
    UIType GetType(UIBase ui)
    {
        foreach (var item in m_UIInfo) {
            if (item.ui == ui)
                return item.type;
        }
        return UIType._NONE;
    }
    #endregion
    #region public funcs
    public void ShowUI(UIType type)
    {
        if (type == m_CurrentType) {
            return;
        }
        if (m_CurrentType != UIType._NONE) {
            GetUI (m_CurrentType).HideUI ();
        }
        if (type != UIType._NONE && m_NextType == UIType._NONE) {
            m_NextType = type;
            GetUI (m_NextType).ShowUI ();
        }
        m_CurrentType = m_NextType;
        m_NextType = UIType._NONE;
    }
    public void HideUI(UIType type){ }
    #endregion
}

要打开某个UI只需要调用一下UIManager.Instance.ShowUI (UIType._GAMEOVER);
就可以了。这样是不是很方便呢。

–Rocky

没有更多推荐了,返回首页