IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity/C#知识点 -- Lambda表达式、委托Delegate、事件Event、Action、Func、UnityAction、UnityEvent综述 -> 正文阅读

[游戏开发]Unity/C#知识点 -- Lambda表达式、委托Delegate、事件Event、Action、Func、UnityAction、UnityEvent综述

Lambda表达式

Lambda表达式本质上就是定义匿名函数

1 Lamba表达式基本结构

(形参列表) => {函数体};   // 当形参只有一个时可以省去"()", 当函数体内只有一段语句时可以省去"{}"

2 将函数改写为Lambda表达式

2.1 无返回值无参数时

void Func1()
{
	Debug.Log("Func1 call");
}
// Lambda表达式:
() => {Debug.Log("Func1 call");Debug.Log("Func100 call");};
() => Debug.Log("Func1 call");   // 如果匿名函数内部只有一段话,可以省去"{}"

2.2 有参数无返回值时

void Func2(int a)
{
    a *= a;
    Debug.Log(a);
}
// Lambda表达式:
(a) => {a *= a; Debug.Log(a);};
a => {a *= a; Debug.Log(a);};

2.3 有返回值有参数时

int Func3(int a, int b)
{
    return a + b;
}
// Lambda表达式
int res = (a, b) => {return a + b;};  // 存在返回值时不可以省略"{}"

委托Delegate

委托可以理解为存储方法的数组,通过委托可以将几个具有相同形参类型和返回值类型的方法加入到一个委托中一并执行

1 定义委托

private int delegate VoidDelegate(int a, int b);   // 括号内为传递的参数

2 实例化委托

VoidDelegate d1; 
VOidDelegate d1 = new VoidDelegate(Func1);   // 如果利用new关键字定义委托,同时需要为其赋初值

3 向委托中添加/删除函数

d1 = Func1;    // 添加第一个函数时需要直接赋值
d1 += Func2;   // 注意这里只能传递一个函数名进去,如果函数名后面加了括号,就会执行该函数一次,这是我们不期望的
d1 += Func3;   
d1 -= Func1;

4 调用委托

d1();    // 直接调用
d1.Invoke(a, b)   // 利用Invoke调用

完整代码

public delegate int IntDelegate(int a, int b);
private void IntDelegateTest()
{
    IntDelegate id;
    id = (a, b) => { return a + b; };
    id += (a, b) => { return a - b; };
    id += (a, b) => { return a * b; };
    int res = id.Invoke(1, 2);   // int res = id(1, 2);
    Debug.Log(res);
}
// 返回值为2,当委托存在返回值时,就只会返回最后加进去的函数的返回值

输出结果:
在这里插入图片描述

委托的使用类内和类外无差别

事件Event

事件可以理解为委托的一个实例(不太严谨),在类的内部声明事件,必须先声明该事件对应的委托类型

同时事件不仅可以添加函数进去,还可以加入委托

public delegate void VoidDelgate(int a);
public static event VoidDelgate voidEvent;
private void VoidEventTest()
{
    // 先定义一个委托
    VoidDelgate vd;
    vd = a => Debug.Log(a);
    vd += a => Debug.Log(a * a);

    // 向事件内添加委托和函数
    voidEvent = vd;
    voidEvent += a => Debug.Log(a - 1);
    voidEvent += a => Debug.Log(a + 1);
    voidEvent(6);
}

输出结果:

在这里插入图片描述

事件与委托的区别:

  • 委托创建时会定义方法的类型(是否有无参数、有无返回值)
  • 事件的创建需要一个委托才能声明(因为事件就是委托的实例)
  • 委托可以在任何类中或类外声明,但是事件只能在类中声明(类型跟实例,实例要运行所以要在类里面咯)
  • 事件只能在当前声明的类中调用,但是可以在其他类中为其添加/删除函数,无论将事件设置成public还是static其他类都无法调用

Action

Action可以理解为系统定义好的带泛型的delegate,Action是无返回值的

要使用Action需要引用头文件

using System;

Action的泛型T代表参数,T内可以传多个参数

private void ActionTest()
{
    Action action;   // 无参的Action
    action = () => Debug.Log("action use once");
    action += () => Debug.Log("action use twice");
    action();

    Action<int, string> action2;   // 有多个参数的Action
    action2 = (a, b) => Debug.Log("name: " + b + "\tage: " + a.ToString());
    action2 += (a, b) => Debug.Log("name: " + b + "\tage: " + (a + 1).ToString());
    action2(18, "Ousun");
}

输出结果:
在这里插入图片描述

Func

Func可以理解为系统定义好的带泛型的delegate,Func是有返回值的

要使用Func需要引用头文件

using System;

Func<T,K>的前n-1个泛型代表参数, 最后一个泛型代表返回值类型

private void FuncTest()
{
    Func<int, int> func;
    func = (a) => { Debug.Log(a); return a; };
    func += (a) => { a += 1; Debug.Log(a); return a; };
    func += (a) => { a += 2; Debug.Log(a); return a; };
    int res = func(1);
    Debug.Log("res = " + res.ToString());
}

输出结果:
在这里插入图片描述

UnityAction

UnityAction是Unity对C#中Action的再封装,是更适合再Unity中使用的一种泛型委托,用法和Action一样

需要包含头文件:

using UnityEngine.Events;
private void UnityActionTest()
{
    UnityAction action;   // 无参的Action
    action = () => Debug.Log("action use once");
    action += () => Debug.Log("action use twice");
    action();

    UnityAction<int, string> action2;   // 有多个参数的Action
    action2 = (a, b) => Debug.Log("name: " + b + "\tage: " + a.ToString());
    action2 += (a, b) => Debug.Log("name: " + b + "\tage: " + (a + 1).ToString());
    action2(18, "Ousun");
}

输出结果:

在这里插入图片描述

UnityEvent

UnityEvent可以在面板中添加监听事件,也可以在代码中添加监听事件或UnityAction

public UnityEvent<int, string> myEvent;

UGUI中的Buttom点击事件,就继承自UnityEvent,可以将UnityEvent显示在监视器面板中
在这里插入图片描述

在代码中调用event,只能使用Invoke方法调用,同时,UnityEvent内添加的方法可以是UnityAction

用 AddListener 和 RemoveListener 分别为事件添加和移除方法

public UnityEvent<int, string> myEvent;
private void UnityEventTest()
{
    myEvent.AddListener((a, b) => 
    { 
    	Debug.Log("name: " + b + "\tage: " + a.ToString()); 
    });
    myEvent.AddListener((a, b) =>
    {
    	Debug.Log("name: " + b + "\tage: " + (a + 1).ToString());
    });
    myEvent.Invoke(18, "Ousun");
}

输出结果:

在这里插入图片描述

配合监视器面板使用:

监视器如下:

在这里插入图片描述

添加的相关函数如下:

public void InspectorEvent(int a, string b)
{
	Debug.Log("InspectorEvent is called");
}

public void InspectorEvent2(int a, string b)
{
	Debug.Log("InspectorEvent2 is called");
}

再次调用上面的UnityEventTest()函数,输出结果如下:

在这里插入图片描述
参考:【Unity知识点】通俗解释delegate,事件event,Action,Func和UnityAction,UnityEvent

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:54:29  更:2022-11-05 00:55:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/22 18:53:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码