【转】 NGUI 监听按钮除OnClick外其他事件的方法,附简易改编的UIButton类

http://blog.csdn.net/icefantasylcj/article/details/49450555

  大家好,我是雨中祈雨。一直以来,CSDN都是我最好的编程助手。这是我在CSDN的第一篇关于Unity3D的博客,其实也就是记录我在学习Unity3D时遇到的一些小问题从不懂到有所了解的过程。另一方面,如果能帮助到遇到过同样问题的Unity3D初学者朋友们,那就再好不过了。

  NGUI是一款非常好用的Unity3D插件,其简单的操作、强大的分辨率自适应以及效果良好的缓动动画等等都是大家青睐于它的原因。今天我就和大家分享一下我在实现NGUI事件监听过程中遇到的一些问题及其解决方法。 
  为按钮添加OnClick事件是比较简单的,做法是将需要在按钮点击时调用的公有方法写在一个继承自MonoBehavior类的脚本中,并将该脚本绑定在任意GameObject对象上,然后将该GameObject拖动至UIButton Script上的OnClick事件栏上即可。

using UnityEngine;
using System.Collections;

public class UIController : MonoBehaviour {

    public void OnButtonClick()
    {
        Debug.Log("呀,被点到了!");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

拖动!

还是拖动。。。

运行结果

  另外,如下代码也可以为指定的按钮添加OnClick事件。 
  

using UnityEngine;
using System.Collections;

public class UIController : MonoBehaviour {

    private UIButton button;

    void Awake()
    {
        //假设场景中有个名为Button的GameObject,获取其上绑定的按钮组件
        button = GameObject.Find("Button").GetComponent<UIButton>();
    }

    void Start()
    {
        button.onClick.Add(new EventDelegate(onButtonClick));

#region UI Listener
    void onButtonClick()
    {
        Debug.Log("触发按钮点击事件。");
    }
#endregion
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

  这两做法同样适用于为Slider、ProgressBar等组件添加事件,也算比较方便,而且有助于UI事件的统一管理。不足之处就是需要执行拖动的步骤,而且对按钮来言,只能监听单一的OnClick事件。当遇到需要监听按钮的OnHover、OnDragOver等事件时,这种做法便无能为力了。 
  对于需要监听按钮其他事件的情况(此处以OnHover事件为例),一种方法是自己重载UIButton的OnHover等函数:

    //自定义类CustomButton,继承自NGUI的UIButton
    public class CustomButton : UIButton {

    //重载OnHover函数
    protected override void OnHover(bool isOver)
    {
        //base能够调用基类的同名函数,有点类似于java中的
        //super关键字 Q.Q
        base.OnHover(isOver);
        if (isOver)
        {
            Debug.Log("执行按钮的Hover事件。");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

运行结果

  还有一种方法就是使用UIEventListener去处理各种UI事件,这种方法也是雨松大神向我们推荐过的一种方法(雨松大神威武)。学过Java的朋友们知道,Java中的观察者(Observer)模式在监听各种事件时那是相当的方便。而C#中也有一个同样很优秀的事件(Event)和委托(Delegate)机制。其实文章开始的那种拖动的方法也使用了事件委托机制,在此我就不赘述事件委托机制的原理,只给大家介绍这种机制在NGUI事件监听中的运用。 
仍以OnHover为例:

using UnityEngine;
using System.Collections;

public class UIController : MonoBehaviour {

    private GameObject go_TestButton;

    void Awake()
    {
        //获取Button或者其他组件的GameObject对象
        go_TestButton = GameObject.Find("UI Root/StartUI/ButtonAnchor/Button");
    }

    void Start()
    {
        UIEventListener.Get(go_TestButton).onHover = OnButtonHover;
        //此处可以使用+=运算符添加多个事件
        //如:UIEventListener.Get(go_TestButton).onHover += OnButtonHover;
    }

    public void OnButtonHover(GameObject btn,bool isOver)
    {
        if (isOver)
        {
            Debug.Log("执行"+btn.name+"按钮的OnHover事件");
        }
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

  这样的话也可以监听Button的其他事件。不过,对于其他的事件来说,相应的函数参数也要进行改变。因为不同委托的事件类型是不一样的。看UIEventListener源码:

    //delegate 委托关键字
    //其形式有点类似于C的函数指针-_-
    public delegate void VoidDelegate (GameObject go);
    public delegate void BoolDelegate (GameObject go, bool state);
    public delegate void FloatDelegate (GameObject go, float delta);
    public delegate void VectorDelegate (GameObject go, Vector2 delta);
    public delegate void ObjectDelegate (GameObject go, GameObject draggedObject);
    public delegate void KeyCodeDelegate (GameObject go, KeyCode key);

    public VoidDelegate onSubmit;
    public VoidDelegate onClick;
    public VoidDelegate onDoubleClick;
    public BoolDelegate onHover;
    public BoolDelegate onPress;
    public BoolDelegate onSelect;
    public FloatDelegate onScroll;
    public VectorDelegate onDrag;
    public ObjectDelegate onDrop;
    public KeyCodeDelegate onKey;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

  不同委托对应着不同的函数以及函数形参。对于onScroll事件来说,函数的写法就应该这样:

    public void OnScroll(GameObject go,float value)
    {
        //执行事件
    }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

  好了,以上就是使用UIEventListener监听UI事件的方法了。感兴趣的朋友可以去深入了解一下事件委托机制,对于提高编程的效率还是很有帮助的。

  但是,有的同学可能会觉得,第一种方法挺好用的,不仅简单粗暴,而且管理起来也挺方便的,有没有什么办法向OnClick那样将其他的事件列表显示在Inspector面板上呢?答案是有的。这里就要用到Unity3D的Editor类了,这个类的作用就是允许用户对Unity3D编辑器进行一些修改。此处简易改编的原理请去NGUI的源码中探索(提示:UIButtonEditor类)~

话不多说上代码(仍是以Button的OnHover事件为例):

/*这个类请放在Unity3D Assets根目录的Editor目录下*/
using UnityEngine;
using UnityEditor;

[CanEditMultipleObjects]
#if UNITY_3_5
[CustomEditor(typeof(CustomButton))]
#else
[CustomEditor(typeof(CustomButton), true)]
#endif

public class CustomButtonEditor : UIButtonEditor{

    //重载UIButtonEditor的DrawProperties方法,
    //用于在Inspector面板上显示用户自定义的内容
    protected override void DrawProperties()
    {
        base.DrawProperties();

        CustomButton cButton = target as CustomButton;

        NGUIEditorTools.DrawEvents("Mouse Over", cButton, cButton.mouseOver);

        NGUIEditorTools.DrawEvents("Mouse Out", cButton, cButton.mouseOut);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
/*请移除原先Button上的UIButton脚本,并绑定这个继承自UIButton的脚本*/
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class CustomButton : UIButton
{

    public List<EventDelegate> mouseOver = new List<EventDelegate>();

    public List<EventDelegate> mouseOut = new List<EventDelegate>();

    protected override void OnHover(bool isOver)
    {
        base.OnHover(isOver);

        if (current == null && isEnabled)
        {
            current = this;
            if (isOver)
            {
                EventDelegate.Execute(mouseOver);
            }
            else
            {
                EventDelegate.Execute(mouseOut);
            }
            current = null;
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

  由于我水平有限,不清楚如和将OnHover传出的isOver参数传入EventDelegate类的成员中,只好分别定义两个事件MouseOver与MouseOut,还请了解的朋友指点。

  接下来该怎么做……大家都懂了吧?(真·直接拖动法什么的最喜欢了) 
上图:

Inspector面板显示

运行结果

  这是我第一次写博客,很多地方可能表达的都很不到位,还望大家海涵。希望能对同为Unity3D的初学者朋友们起到一定的帮助作用。谢谢!

posted on 2016-12-31 22:15  mimime  阅读(585)  评论(0编辑  收藏  举报