Unity3D 中的System.EventHandler使用详解

在本文,你将学到如何在Unity3D中使用系统自带委托EventHandler完成事件的声明订阅和执行;

写在前面:

EventHandler是什么?
System.EventHandler是IDE提供的封装好含有2个参数(object sender ,EventArgs e)的委托,前面参数是事件发送者object sender,后面是事件详情标签(传递事件的细节)EventArgs e
有了这样的体贴入微的委托,我们就不用重新声明类似的委托啦!

如何用在Unity3d呢?

要想在Unity3D里面使用呢,肯定就是被订阅的方法签名必须与委托定义的签名保持一致呀。

方法必须形如:void MethodName(object sender,EventArgs e){yourCode};

但是这样问题就来啦:

  1. 我怎么能把我们的游戏对象作为参数传过去呢?
  2. 我怎么拿出EventArgs的信息呢?

首先讲讲第一个参数:
在Unity3D里面,所有物体均可称为一个游戏对象GameObject,而它的基类就是object,完美,也就是说Unity3D里面的游戏对象都可以作为事件发送方出现在这个委托的第一个参数里面呢~

其次我们说说第二个参数:
EventArgs是事件详情类的基类,在Unity3D里面直接使用得不到啥有用的信息,咋整?
其实,需要我们继承这个基类,写自己的事件详情页:MyEventArgs,想要订阅的方法得到啥你就把啥整进去就好咯!
然后,事件执行的时候new一个MyEventArgs的对象,传进去就好啦!

原理我们懂了,现在具体实现下:

首先,写一个类EventSender,利用EventHandler声明事件OnMoveCompleteHandle,并公开执行方法DoItNow()让外部可以主动执行那些订阅了事件的方法(在EventSender类中也可以定义如何执行这个事件,但是宝宝不写)

using UnityEngine;
using System;
public class EventSender : MonoBehaviour
{
    public event EventHandler OnMoveCompleteHandler;
    /// 
    /// 事件触发执行的方法,Public方便外界调用,谁执行,谁给执行细节
    /// 
    /// 谁执行,谁就传递GameObject
    /// 谁执行,谁就传递事件细节信息,如果自定义的,就New一个,如果是系统默认的就用EventARgs.Empty确保签名一致性
    public void DoItNow(GameObject go, MyEventArgs e)  //这个在执行时由外部触发方传参数,谁执行谁定义参数,很灵活方便
    {
        if (OnMoveCompleteHandler != null)
        {
            OnMoveCompleteHandler(go, e);
        }
    }
    public void DoItNow()//这个不管是谁外部触发的,参数均为EventSender预先定义OK的,显然很多不便
    {
        if (OnMoveCompleteHandler != null)
        {
            OnMoveCompleteHandler(gameObject, new MyEventArgs(520, "事件详情生成方为事件声明方,也就是“EventSender”"));
        }
    }
}

自定义信息细节类:

在这个类,你可以把事件发布方,执行方亦或是订阅方的家底都打包抛出去

using System;

/// 
/// 继承EventArgs自定义自己的事件细节信息,这里只演示传递2种变量信息,实际使用可传递的信息那就多了,你想传啥都可以;/// 
public class MyEventArgs : EventArgs
{
    private string message;
    private int id;
    public string Message{ get { return message; } private set { message = value; } }
    public int Id{get{return id;}private set { id = value; } }
    public MyEventArgs(int _id,string _message)
    {
        Id= _id;
        Message = _message;
    }
}

写一个订阅事件的类:

using System;
using UnityEngine;

public class EventReceive : MonoBehaviour {
    public EventSender tc;
    void Start()
    {
        tc.OnMoveCompleteHandler += TestFunc; //事件的订阅
    }

    private void TestFunc(object sender, EventArgs e)//具体执行的方法,函数签名必须与委托定义的保持一致
    {
        GameObject go = (GameObject)sender; //我们知道我们传递了什么过来;
        MyEventArgs ag = (MyEventArgs)e;       //所以强转获得事件执行方给的各种信息;
        Debug.Log("游戏对象是:" + go.name + ";消息是:“" + ag.Message + "”,消息ID为:" + ag.Id);
    }
    void Update()
    {
        if (Input.GetMouseButtonDown(0))  //按左键执行事件,这个事件里面传递的值是预先定义的哈,改不了
        {
            Debug.Log("我按下了左键");
            tc.DoItNow();
        }
        else if (Input.GetMouseButtonDown(1))//按右键执行另一个重载,这下我们能自由发挥给我们的订阅者发送我想给的参数啦,是不是感觉好畅快呀!
        {
            Debug.Log("我按下了右键");
            tc.DoItNow(gameObject, new MyEventArgs(520520, "事件详情生成方为事件订阅方,也就是“EventReceive”"));
        }
    }
}

动画演示一下:

Unity3D 中的System.EventHandler使用详解_第1张图片
test.gif

如何结合UI控件使用呢?

结合笔者前面写的UGUI Button OnClick事件统一管理,将Update里面测试用的那句写到AddListener里面就可以实现啦~

直接上手测试UnityPackage

Demo下载地址

标签:Unity3D、事件系统、EventHandler,EventArgs、在Unity中使用EventHandler

你可能感兴趣的:(Unity3D 中的System.EventHandler使用详解)