Unity 自定义委托以及事件解读
如果有说的不对的地方欢迎指正。
资料参考:小Joe的学习课堂 哈哈哈.
目录
什么是委托
委托:引用类型的数据类型
关键字:delegate
定义:委托可以封装一个或者多个方法
委托类型的实例可以和任何其他方法相关联起来,只要类型兼容
换句话说就是只要返回值和签名相同就可以通过委托实例来间接调用这些方法
如何声明一个委托
//委托声明
// public 公开程度 delegate 关键字 void 目标方法的返回值 参数 空
//_Delegate 可匹配方法(类型兼容):参数以及返回值为空的方法
//无参
public delegate void _Delegate();
//带参
public delegate string _DelegateStr(string _PrintStr);
自定义委托变量声明以及Unity 封装委托变量声明
//自定义委托变量
private _Delegate _MyDelegate;
private _DelegateStr _MyDelegateStr;
// Action 委托定义: 可兼容无返回值有参方法 无法兼容有返回值方法
private Action _MyAction;
private Action<string> _MyActionStr;
// Func 委托定义: 可兼容有返回值有参方法 无法兼容无返回值方法
//书写格式 < 参数类型 , 返回值类型 >
private Func<int, string> _MyFunc;
private Func<string> _MyFuncStr;
委托消息分发
注意一点如果自定义委托是用 “=”操作符是会覆盖当前所属同属性广播的。
举个例子:A+=A ; Pint(A); 会输出不同值,但是 A=A ; Pint(A);会输出单一值。
可能有那一点不是很形象,但也差不太多【尴尬】其实自己试一下就知道我说的什么意思了。
//消息分发
//委托可使用单路广播的形式
_MyDelegate = new _Delegate(DebugLog);
_MyDelegateStr = new _DelegateStr(DebugLogStr);
_MyAction = new Action(DebugLog);
_MyActionStr = new Action<string>(DebugLogStrNot);
_MyFunc = new Func<int, string>(DebugLogStrInt);
_MyFuncStr = new Func<string>(DebugLogStrOut);
//也可使用多路广播的形式
//执行的顺序也还是添加方法的顺序
_MyDelegate += DebugLog;
_MyDelegate += DebugLog02;
_MyDelegate += DebugLog03;
_MyAction += DebugLog;
_MyAction += DebugLog02;
_MyAction += DebugLog03;
委托执行
//执行
//不带参数
_MyDelegate();
_MyAction();
_MyFuncStr();
//带参数
_MyDelegateStr("_MyDelegateStr");
_MyActionStr("_MyActionStr");
_MyFunc(12);
委托销毁
/// <summary>
/// 当前脚本 关闭的时候 注销委托方法 繁殖内存泄漏
/// </summary>
private void OnDestroy()
{
//注销委托方法
_MyDelegate -= new _Delegate(DebugLog);
_MyDelegate -= new _Delegate(DebugLog02);
_MyDelegate -= new _Delegate(DebugLog03);
_MyAction -= DebugLog;
_MyAction -= DebugLog02;
_MyAction -= DebugLog03;
}
自定义委托代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 自定义委托
/// </summary>
public class CustomDelegate_ZH : MonoBehaviour
{
//委托关键字:delegate
//委托:引用类型的数据类型
//定义:委托可以封装一个或者多个方法
//委托类型的实例可以和任何其他方法相关联起来,只要类型兼容 换句话说就是只要返回值和签名相同就可以通过委托实例来间接调用这些方法
//委托声明
// public 公开程度 delegate 关键字 void 目标方法的返回值 参数 空
//_Delegate 可匹配方法(类型兼容):参数以及返回值为空的方法
public delegate void _Delegate();
//带参
public delegate string _DelegateStr(string _PrintStr);
//自定义委托变量
private _Delegate _MyDelegate;
private _DelegateStr _MyDelegateStr;
// Action 委托定义: 可兼容无返回值有参方法 无法兼容有返回值方法
private Action _MyAction;
private Action<string> _MyActionStr;
// Func 委托定义: 可兼容有返回值有参方法 无法兼容无返回值方法
//书写格式 < 参数类型 , 返回值类型 >
private Func<int, string> _MyFunc;
private Func<string> _MyFuncStr;
/// <summary>
/// 当前对象激活时执行
/// </summary>
private void OnEnable()
{
//消息分发
//委托可使用单路广播的形式
_MyDelegate = new _Delegate(DebugLog);
_MyDelegateStr = new _DelegateStr(DebugLogStr);
_MyAction = new Action(DebugLog);
_MyActionStr = new Action<string>(DebugLogStrNot);
_MyFunc = new Func<int, string>(DebugLogStrInt);
_MyFuncStr = new Func<string>(DebugLogStrOut);
//也可使用多路广播的形式
//执行的顺序也还是添加方法的顺序
_MyDelegate += DebugLog;
_MyDelegate += DebugLog02;
_MyDelegate += DebugLog03;
_MyAction += DebugLog;
_MyAction += DebugLog02;
_MyAction += DebugLog03;
#region //委托执行
//执行
//不带参数
_MyDelegate();
_MyAction();
_MyFuncStr();
//带参数
_MyDelegateStr("_MyDelegateStr");
_MyActionStr("_MyActionStr");
_MyFunc(12);
#endregion
}
/// <summary>
/// 当前脚本 关闭的时候 注销委托方法 繁殖内存泄漏
/// </summary>
private void OnDestroy()
{
//注销委托方法
_MyDelegate -= new _Delegate(DebugLog);
_MyDelegate -= new _Delegate(DebugLog02);
_MyDelegate -= new _Delegate(DebugLog03);
_MyAction -= DebugLog;
_MyAction -= DebugLog02;
_MyAction -= DebugLog03;
}
/// <summary>
/// 委托匹配方法
/// 说明:无返回值、无参数
/// </summary>
public void DebugLog()
{
Debug.Log("无参无返回值 委托调用成功:DebugLog");
}
/// <summary>
/// 无返回值无参 方法
/// </summary>
private void DebugLog02()
{
Debug.Log("无参无返回值 委托调用成功:DebugLog02");
}
/// <summary>
/// 无返回值无参 方法
/// </summary>
private void DebugLog03()
{
Debug.Log("无参无返回值委托调用成功:DebugLog03");
}
/// <summary>
/// 无返回值有参 方法
/// </summary>
/// <param 参数="_Str"></param>
private void DebugLogStrNot(string _Str)
{
_Str = _Str + ":无返回值有参 委托调用成功:DebugLogStrNot";
Debug.Log(_Str);
}
/// <summary>
/// 有返回值无参 方法
/// </summary>
/// <param 参数="_Str"></param>
private string DebugLogStrOut()
{
string _Str = "";
_Str = _Str + ":有返回值无参 委托调用成功:DebugLogStrOut";
Debug.Log(_Str);
return _Str;
}
/// <summary>
/// 有返回值 有参 方法
/// </summary>
/// <param 参数="_Str"></param>
/// <returns></returns>
private string DebugLogStr(string _Str)
{
_Str = _Str + ":有参有返回值 委托调用成功:DebugLogStr";
Debug.Log(_Str);
return _Str;
}
/// <summary>
/// 有返回值 有参 方法
/// </summary>
/// <param 参数="_Int"></param>
/// <returns></returns>
private string DebugLogStrInt(int _Int)
{
string _Str;
_Str = _Int.ToString() + ":有参有返回值 委托调用成功:DebugLogStr";
Debug.Log(_Str);
return _Str;
}
}
委托基础执行结果
什么是事件
事件:事件是属于类的成员,事件就是委托的封装
关键字:event
定义:C# 中使用事件机制实现线程间的通信。
总结:事件只能 Add、Remove 事件处理器不能赋值。并且事件只能执行 +=、-=,不能=、不能外部触发事件。
事件模型的五个组成部分
//事件模型的五个组成部分
//1. 事件的拥有者【类】 ------> Custom类
//2. 事件【event关键字】 ------> _OnOrder事件
//3. 事件的响应者【类】 ------> ResponseEvent类
//4. 事件的处理器【方法-受到约束的方法】 ------>Response方法
//5. 事件的订阅关系【+=】 ------> +=
//触发事件的对象称为事件发送者;接收事件的对象称为事件接收者。
如何声明一个事件(简略格式)
//事件声明
public event OrderEventHandler _OnOrder
事件声明完整格式
//事件声明完整格式
//声明一个委托变量
//用途:用来存储、引用事件处理器的
private OrderEventHandler _OrderEventHandler;
//事件声明
public event OrderEventHandler _OnOrder
{
//添加事件处理器的【添加器】和【移除器】
add
{
_OrderEventHandler += value;
}
remove
{
_OrderEventHandler -= value;
}
}
//内部执行逻辑
public void Order()
{
//判断委托类型是否为空 是否有人订阅当前委托
if (_OrderEventHandler != null)
{
//创建事件响应参数 实例
OrderEnevetArgs _E = new OrderEnevetArgs();
_E.EventAtgsStr = "事件处理A";
_E.Price = 15;
//参数: 事件发送者、拥有者 事件参数
_OrderEventHandler(this, _E);
}
}
如何调用一个事件
_MyCustom._OnOrder += _ResponseEvent.Response;
第一版完整代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 自定义事件
/// </summary>
public class CustomEvent_ZH : MonoBehaviour
{
//事件模型的五个组成部分
//1. 事件的拥有者【类】 ------> Custom类
//2. 事件【event关键字】 ------> _OnOrder事件
//3. 事件的响应者【类】 ------> ResponseEvent类
//4. 事件的处理器【方法-受到约束的方法】 ------>Response方法
//5. 事件的订阅关系【+=】 ------> +=
//触发事件的对象称为事件发送者;接收事件的对象称为事件接收者。
//创建事件拥有者的实列
Custom _MyCustom = new Custom();
//事件响应者
ResponseEvent _ResponseEvent = new ResponseEvent();
//事件是基于委托的
//委托是事件的底层基础
//事件是委托的上层建筑
//1. 类型兼容 :事件需要使用委托类型来做一个约束
private void Start()
{
_MyCustom._OnOrder += _ResponseEvent.Response;
}
}
/// <summary>
/// 委托
/// 如果使用 EventHandler 为后缀 说明当前委托类型是用来 使用事件处理的
/// 参数:事件拥有者 事件参数
/// </summary>
public delegate void OrderEventHandler(Custom _Custom, OrderEnevetArgs _E);
/// <summary>
/// 事件拥有者
/// </summary>
public class Custom
{
//属性
//账单
public float Bill { get; set; }
//资产
public int MyProperty { get; set; }
//
public void PayTheBill()
{
Debug.Log("事件处理器" + Bill);
}
//事件声明简略格式
public event OrderEventHandler _OnOrder;
#region //事件声明完整格式
//事件声明完整格式
//声明一个委托变量
//用途:用来存储、引用事件处理器的
private OrderEventHandler _OrderEventHandler;
//事件声明
public event OrderEventHandler _OnOrder01
{
//添加事件处理器的【添加器】和【移除器】
add
{
_OrderEventHandler += value;
}
remove
{
_OrderEventHandler -= value;
}
}
//内部执行逻辑
public void Order()
{
//判断委托类型是否为空 是否有人订阅当前委托
if (_OrderEventHandler != null)
{
//创建事件响应参数 实例
OrderEnevetArgs _E = new OrderEnevetArgs();
_E.EventAtgsStr = "事件处理A";
_E.Price = 15;
//参数: 事件发送者、拥有者 事件参数
_OrderEventHandler(this, _E);
}
}
#endregion
}
/// <summary>
/// 事件参数传递
/// 如果一类的用途作为 EvenetArgs类 来使用 就要继承于EvenetArgs类(事件参数)
/// </summary>
public class OrderEnevetArgs : EventArgs
{
//事件响应名字
public string EventAtgsStr { get; set; }
//价格
public float Price { get; set; }
}
/// <summary>
/// 事件响应者
/// </summary>
public class ResponseEvent
{
internal void Response(Custom _Custom, OrderEnevetArgs _E)
{
//价格
float _ResponsePrice = 0.0f;
switch (_E.EventAtgsStr)
{
case "事件处理A":
_ResponsePrice = _E.Price;
break;
case "事件处理B":
_ResponsePrice = _E.Price + 3;
break;
case "事件处理C":
_ResponsePrice = _E.Price + 6;
break;
default:
break;
}
//账单
_Custom.Bill += _ResponsePrice;
}
}
最后完整代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 自定义事件
/// </summary>
public class CustomEvent_ZH : MonoBehaviour
{
//事件模型的五个组成部分
//1. 事件的拥有者【类】 ------> Custom类
//2. 事件【event关键字】 ------> _OnOrder事件
//3. 事件的响应者【类】 ------> ResponseEvent类
//4. 事件的处理器【方法-受到约束的方法】 ------>Response方法
//5. 事件的订阅关系【+=】 ------> +=
//触发事件的对象称为事件发送者;接收事件的对象称为事件接收者。
//创建事件拥有者的实列
Custom _MyCustom = new Custom();
//事件响应者
ResponseEvent _ResponseEvent = new ResponseEvent();
//事件是基于委托的
//委托是事件的底层基础
//事件是委托的上层建筑
//1. 类型兼容 :事件需要使用委托类型来做一个约束
private void Start()
{
_MyCustom._OnOrder += _ResponseEvent.Response;
//事件拥有者的内部逻辑 触发事件
_MyCustom.Order("事件触发器A", 15);
}
}
/// <summary>
/// 事件拥有者
/// </summary>
public class Custom
{
//属性
//账单
public float Bill { get; set; }
//资产
public int MyProperty { get; set; }
//事件处理器
public void PayTheBill()
{
Debug.Log("事件处理器" + Bill);
}
//事件声明简略格式
public event EventHandler _OnOrder;
//内部执行逻辑
public void Order(string _Name, float _Price)
{
//如果事件不为空
if (_OnOrder!=null)
{
OrderEnevetArgs _OrderEnevetArgs = new OrderEnevetArgs();
_OrderEnevetArgs.EventAtgsStr = _Name;
_OrderEnevetArgs.Price = _Price;
//参数: 事件发送者、拥有者 事件参数
_OnOrder(this, _OrderEnevetArgs);
}
}
}
/// <summary>
/// 事件参数传递
/// 如果一类的用途作为 EvenetArgs类 来使用 就要继承于EvenetArgs类(事件参数)
/// </summary>
public class OrderEnevetArgs : EventArgs
{
//事件响应名字
public string EventAtgsStr { get; set; }
//价格
public float Price { get; set; }
}
/// <summary>
/// 事件响应者
/// </summary>
public class ResponseEvent
{
internal void Response(object sender, EventArgs e)
{
//价格
float _ResponsePrice = 0.0f;
// as 类型转换
Custom _Custom = sender as Custom;
OrderEnevetArgs _OrderEnevetArgs = e as OrderEnevetArgs;
switch (_OrderEnevetArgs.EventAtgsStr)
{
case "事件处理A":
_ResponsePrice = _OrderEnevetArgs.Price;
break;
case "事件处理B":
_ResponsePrice = _OrderEnevetArgs.Price + 3;
break;
case "事件处理C":
_ResponsePrice = _OrderEnevetArgs.Price + 6;
break;
default:
break;
}
//账单
_Custom.Bill += _ResponsePrice;
}
}
大总结!!!(敲黑板)
委托和事件的关系?
答:事件不是委托类型的字段也不是一种特殊类型的字段。
事件只是委托的包装器、限制器,限制外界对委托类型的字段访问,但并不是委托字段的本身。
为什么要使用委托类型来声明事件?
答:因为委托类型可以完美保存、记录、存储,并响应事件。
暂时先这样吧,如果有时间的话就会更新,实在看不明白就留言,看到我会回复的。
路长远兮,与君共勉。