Unity3D中使用委托和事件(一)

前言:

本来早就想写写和代码设计相关的东西了,以前做2DX的时候就有过写写观察者设计模式的想法,但是实践不多。现在转到U3D的怀抱中,倒是接触了不少委托事件的写法,那干脆就在此总结一下吧。

1.C#中的委托、事件引入

本想去找一些高端的介绍来开场,但是找来找去感觉还是用百度百科中的例子来开场也是蛮适合的。当然要具体到Unity3d,我们还是要按照U3d的格式来写。

首先我们来看百度百科这个例子写的是什么?

ok,原来是全球化形势下,不同语种的小伙伴们问候早安时候的一个情景。那么最直观的做法,无非是判断哪国人,然后说英语的调用说英语的方法,说中文的调用说中文的方法,之后再有说日语的,说法语的还要再调用说日语的,说法语的方法。这样做当然OK,但是拓展性很差。

首先是不考虑使用委托时的写法

using UnityEngine;
using System.Collections;

public class delegateFanyoy : MonoBehaviour {

	// Use this for initialization
	public UIButton testBtn;
	void Start () {
		EventDelegate.Add (this.testBtn.onClick, this.BtnClick);
	}
	public void BtnClick()
	{
		GoodMoring ("chenjd");
	}

	public void GoodMoring(string name)
	{
		Debug.Log ("GoodMoring " + name);
	}
	// Update is called once per frame
	void Update () {

	}
}

  很简单,首先利用EventDelegate为按钮的OnClick事件绑定一个方法,用来测试我们上面提到的问早安的功能。

结果如下:

那么问题来了,小匹夫可是堂堂中国人啊,怎么能不说中文反而天天鼓捣英语呢?所以刚刚实现问早的方法GoodMoring()就不能用咯,还要新写一个方法,要输出中文早安,然后再和点击按钮的事件绑定。这样是不是很麻烦呢?

如果有小伙伴觉得不麻烦,那小匹夫只能演示一种小匹夫认为不使用委托的前提下最直接的一种写法了。这时候,GoodMoring就需要改一改了,肯定要根据不同的人来选择不同的问候语咯。这里为了方便,定义一个枚举Language作为判断的依据:

using UnityEngine;
using System.Collections;

public class delegateFanyoy : MonoBehaviour {

	// Use this for initialization
	public UIButton testBtn;
	void Start () {
		EventDelegate.Add (this.testBtn.onClick, this.BtnClick);
	}
	public void BtnClick()
	{
		GoodMoring ("chenjd", Language.Chinese);
	}

	public void GoodMoring(string name, Language l)
	{
		switch (l)
		{
		case Language.Chinese:
			MoringChinese(name);
			break;
		case Language.English:
			MoringEnglish(name);
			break;
		}
	}

	public void MoringChinese(string n)
	{
		Debug.Log ("早上好 " + n);
	}

	public void MoringEnglish(string n)
	{
		Debug.Log ("goodmoring" + n);
	}

	public enum Language
	{
		Chinese,
		English
	}
	// Update is called once per frame
	void Update () {

	}
}

如果再来一个日语普通话的小伙伴,或者再来一个韩语思密达的小伙伴,那么不可避免我们需要去修改GoodMoring这个函数去实现判断并调用正确的语言输出方法。这样拓展性体现在哪里呢?

如果说能有一个方法A,它的参数也是一个方法B,那么我们保留那个方法A而只需要传入不同的参数(方法B),不就可以灵活的应对了吗?再来一个日本人,一个韩国人,无非只是将说日语和说韩语的方法B传入到那个无需改动的方法A中就可以了,点击按钮触发的事件只需要方法A响应就可以咯。这里方法A就是我们的GoodMoring方法,而方法B作为参数是不同语言的MoringXXXX方法。

那么我们就可以引入代理的概念了。嗯,是那句很老套的——方法的参数是方法。

2.方法的参数是方法
那么我们开始进行第一步分析,千里之行始于足下嘛。

既然方法A的某个参数是方法B,我们所要利用的无非就是使用传入的方法B。所以我们之前的方法A--GoodMoring(string name, language l)方法就变成了

GoodMoring(string name, XXX MoringLanguage)
{
    MoringLanguage(name);
}

直接调用作为参数传入的方法。  

但是这里又有新的问题出现了,涉及到要将方法作为参数传入另一个方法,我们都知道,参数的传入是需要有类型的呀。你MoringLanguage到底是个啥?

这里我们似乎又想到了,区分方法,无非是它的返回值,和传入参数类型个数。想到这里,豁然开朗,只要我们规定了传入的MoringLanguage的返回类型和MoringLanguage的参数类型是不是就可以证明传入的MoringLanguage的身份了呢?对!这就是代理了delegate了。

那我们按照MoringChinese和MoringEnglish的返回类型和参数类型来定义这个委托。

public delegate void MoringDelegate(string name);

那么我们将GoodMoring的修改为

GoodMoring(string name, MoringDelegate MoringLanguage)
{
    MoringLanguage(name);
}

就可以了。下面上代码。

using UnityEngine;
using System.Collections;

public class delegateFanyoy : MonoBehaviour {

	// Use this for initialization
	public UIButton testBtn;
	void Start () {
		EventDelegate.Add (this.testBtn.onClick, this.BtnClick);
	}
	public void BtnClick()
	{
		GoodMoring ("chenjd", MoringEnglish);
		GoodMoring ("小匹夫", MoringChinese);

	}

	public void GoodMoring(string name, MoringDelegate MoringLanguage)
	{
		MoringLanguage (name);
	}
	public delegate void MoringDelegate(string n);

	public void MoringChinese(string n)
	{
		Debug.Log ("早上好 " + n);
	}

	public void MoringEnglish(string n)
	{
		Debug.Log ("goodmoring" + n);
	}

	public enum Language
	{
		Chinese,
		English
	}
	// Update is called once per frame
	void Update () {

	}
}

  

最后,做个小结,也用一句在网上烂大街的话好了。所谓委托就是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If … Else(Switch)语句,同时使得程序具有更好的可扩展性哟。

时间: 2024-08-08 12:23:04

Unity3D中使用委托和事件(一)的相关文章

C# 委托与事件的例子

今天在一个项目中看到委托与事件的使用,故重新整理一个简单易懂的例子,仅供参考而已. namespace DelegateAndEvent { public delegate void delegateTest(int a);//定义一个委托 public delegate void delegateErr(Exception e);//定义一个报错委托 class Program { static void Main(string[] args) { object r = Console.Rea

委托和事件 (2) - 事件

事件的由来 上文说到委托的安全性不佳,于是我们要将委托本身私有化,但还要暴露若干方法让外界使用.其中最重要的必然就是为委托挂接方法和调用委托,以便间接地调用委托所代表方法.那么事件event关键字就是c#提供给我们的一个语法糖.他并没有任何新的东西,只是减少了一些代码.所以,事件是一种特殊的委托,其特征有: 1 和一个(基底)委托类型合作,当声明了一个具有该基底委托类型的事件之后,用户在外部就可以为这个事件挂接方法,其方法类型必须和基底委托类型相同 2 可以将事件视为委托的方法链,使用event

C#一些知识点:委托和事件的区别

在C#中,委托和事件是比较容易混淆的两个知识点,本篇博客就记录一下委托和事件之间的区别. 定义上的区别 委托:委托实际上是一个类,用来表示一个函数,可以理解为C++中的函数指针. 事件:事件是一个修饰符,用来修饰一个委托类型的属性,表示该委托的部分功能被限制了. 我们可以这么理解:委托是类,定义了委托后,就可以像使用类一样的来使用这个委托,而事件修饰了委托后则是表示限制这个委托的部分功能,使其满足作为事件的规则. 那么事件究竟限制了委托的什么功能呢?主要是下面的这两个限制: 调用的限制 委托的调

在Unity3D中基于订阅者模式实现事件机制

??各位朋友,大家好,欢迎大家关注我的博客,我是秦元培,我的博客地址是http://qinyuanpei.com.今天博主想和大家分享的是在Unity3D中基于订阅者模式实现消息传递机制,我们知道Unity3D中默认提供了一种消息传递机制SendMessage,虽然SendMessage使用起来的确非常简单,可是它的这种简单是建立在付出一定的代价的基础上的.经常有朋友提及不同的模块间如何进行通信的问题,可能答案最终会落到单例模式.委托和事件机制这些关键词上,在这种情况下本文所探讨的内容可能会帮助

C#中委托和事件

目 录 1.1 理解委托 2 1.1.1 将方法作为方法的参数 2 1.1.2 将方法绑定到委托 4 1.2 事件的由来 6 1.2.1 更好的封装性 6 1.2.2 限制类型能力 9 1.3 委托的编译代码 10 1.4 .NET 框架中的委托和事件 11 1.4.1 范例说明 11 1.4.2 Observer 设计模式简介 12 1.4.3 实现范例的Observer 设计模式 13 1.4.4 .NET 框架中的委托与事件 14 1.5 委托进阶 16 1.5.1 为什么委托定义的返回值

Unity3D中事件函数的运行顺序

Unity3D中脚本的生命周期是依照预先定义好的事件函数的运行流程来演化的,详细流程例如以下: Editor模式下Reset: 当脚本第一次被挂到GameObject上或用户点击Resetbutton时,Reset被调用初始化脚本属性,最经常使用于在Inspector视图中呈现好的默认值. 载入第一个场景First Scene Load: 场景启动时会对场景中的每一个对象运行一遍例如以下事件函数: Awake:游戏启动之前初始化不论什么变量和游戏状态,仅在脚本生命周期中调用一次.不能做协程,St

C#中委托和事件的区别

大致来说,委托是一个类,该类内部维护着一个字段,指向一个方法.事件可以被看作一个委托类型的变量,通过事件注册.取消多个委托或方法.本篇分别通过委托和事件执行多个方法,从中体会两者的区别. □ 通过委托执行方法 class Program { static void Main(string[] args) { Example example = new Example(); example.Go(); Console.ReadKey(); } } public class Example { pu

js中的事件委托或是事件代理详解

起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它还有一个名字叫事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.那这是什么意思呢?网上的各位大牛们讲事件委托基本上都用了同一个例子,就是取快递来解释这个现象,我仔细揣摩了一下,这个例子还真是恰当,我就不去想别的例子来解释了

C#中 委托和事件的关系

首先,委托 是一个好东西.按我的理解,委托 是针对 方法 的更小粒度的抽象.比较interface,他精简了一些代码.使得 订阅-通知 (观察者模式)的实现变得非常简洁. 关于事件,我最初的理解是:事件是利用委托  对  通知-订阅模式 的一种实现方式. 我觉得我并没有理解错,但还不够精确. 我现在要问: 为什么要用非要事件来实现 通知-订阅模式? 而不直接用委托呢?事件到底解决了什么问题? 在<果壳中的C# 中文版> P112页 说了. 总的目标是 事件-订阅 模式中,保护订阅互不影响. 如