在Unity中,委托(Delegate
)是一种用于处理方法回调的特殊类型。它允许您将方法作为参数传递给其他方法,并在需要时调用这些方法。
委托在游戏开发中非常有用,特别是在事件处理、消息传递和异步操作方面。它提供了一种灵活的方式来注册和触发方法,而无需显式地知道这些方法的实现细节。
个人理解
:可以把委托理解为一个容器,容器里面放可以放很多函数方法。一调用委托,里面所有的函数方法都会同步被执行
使用委托的优点如下:
解耦性
:使用委托可以帮助解耦代码,使得不同部分之间的依赖关系更加松散。通过将方法作为参数传递给委托,可以将方法的调用从直接依赖于特定对象解耦,从而提高代码的灵活性和可维护性。
可扩展性
:使用委托可以轻松地扩展代码功能。您可以通过在不修改现有代码的情况下注册或替换委托方法来添加新的功能或更改现有功能。这使得您可以将委托用于事件处理和插件系统等场景。
事件驱动
:委托在事件驱动的编程中非常有用。您可以使用委托将方法注册为事件的处理程序,当事件发生时,委托会自动调用所有注册的方法。这样,您可以轻松地实现事件触发和处理的机制。
多线程支持
:在多线程编程中,委托可以用于实现异步操作和回调。您可以将方法传递给线程,让线程在适当的时候调用该方法,以便在后台执行任务并返回结果。
可读性和可维护性
:使用委托可以使代码更具可读性和可维护性。通过使用委托,您可以明确地指定关注点和功能,并将其封装在独立的方法中。这样,代码变得更易于理解、调试和修改。
总的来说,委托提供了一种灵活且强大的机制,可以改善代码结构和组织,并支持一些重要的编程概念,如解耦、事件驱动和多线程编程。它是一种在Unity中常用的工具,可以提高代码的可维护性和可扩展性。
举个例子来使用委托:我们先定义一个宠物名称委托,在TestA类中实现狗和猫的方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public delegate void PetName(string name); //委托 (需要一个string类型的参数当宠物名称)
//陆地动物类
public class TestA : MonoBehaviour
{
PetName petName; //声明委托
void Start()
{
//委托
petName += Dog; //狗
petName += Cat; //猫
//调用委托事件
petName("大白");
}
//狗 因为委托调用所以需要一个string参数
void Dog(string name)
{
Debug.Log($"我叫{name},是一只狗");
}
//猫
void Cat(string name)
{
Debug.Log($"我叫{name},是一只猫");
}
}
从中我们可以看到,当我们把两个方法(狗,猫)“添加”到委托中时,我们只需要调用定义的委托(petName方法) 就可以同时执行添加的两个方法。根据上面的委托的含义来解释,我们创建了一个petName委托当作容器,然后将dog(狗),cat(猫)方法添加到容器中,这样我们只需要执行容器就可以将容器中的所有方法都给执行。
委托创建时会定义方法的类型。(是否有无参数、有无返回值)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public delegate void DelegateA(); //无参无返回值
public delegate void DelegateB(string name); //有参无返回值
public delegate string DelegateC(); //无参有返回值
public delegate string DelegateD(string name); //有参有返回值
//陆地动物类
public class TestA : MonoBehaviour
{
//委托定义
DelegateA delegateA; //无参无返回值
DelegateB delegateB; //有参无返回值
DelegateC delegateC; //无参有返回值
DelegateD delegateD; //有参有返回值
void Start()
{
//添加方法
delegateA = A;
delegateB = B;
delegateC = C;
delegateD = D;
//这里错误示范 delegateA委托添加B方法会报错,原因委托定义了方法类型,B方法类型不符合delegateA定义的方法类型会报错
//delegateA += B;
//运行
delegateA();
delegateB("");
delegateC();
delegateD("");
}
void A()
{
Debug.Log("无参无返回值");
}
void B(string name)
{
Debug.Log("有参无返回值");
}
string C()
{
Debug.Log("无参有返回值");
return "";
}
string D(string name)
{
Debug.Log("有参有返回值");
return "";
}
}
运行结果:
错误示范:
delegateA委托添加B方法会报错,原因委托定义了方法类型,B方法类型不符合delegateAi定义的方法类型会报错
举一个大家经常用的例子,你在CSDN中订阅一个博主的专栏(游戏专栏),当这个博主发布了这个专栏的一个最新文章,就会收到消息。这个就是用的委托,实现如下
1.创建一个博主类Blogger,负责书写文章,并且调用委托事件向订阅专栏的用于发送最新文章
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//这是一个博主类负责书写文章,并且调用委托事件向订阅专栏的用于发送最新文章
public class Blogger : MonoBehaviour
{
public InputField articleName; //文章名称
public Button uploadBtn; //上传文章
void Start()
{
//按钮监听
uploadBtn.onClick.AddListener(UpLoad);
}
//上传事件
void UpLoad()
{
//上传文章名称不为空时
if (articleName.text!=string.Empty)
{
Debug.Log($"博主上传文章:{articleName.text}");
}
}
}
2.创建一个有参无返回值的订阅委托,用于存放订阅人员推送信息方法,并在博主类中声明创建。与上方博主类结合,完整代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public delegate void Subscribe(string name);//订阅委托 用于存放订阅人员的推送方法
//这是一个博主类负责书写文章,并且调用委托事件向订阅专栏的用于发送最新文章
public class Blogger : MonoBehaviour
{
public InputField articleName; //文章名称
public Button uploadBtn; //上传文章
public static Subscribe subscribe; //创建公用的静态订阅委托
void Start()
{
//按钮监听
uploadBtn.onClick.AddListener(UpLoad);
}
//上传事件
void UpLoad()
{
//上传文章名称不为空时
if (articleName.text!=string.Empty)
{
Debug.Log($"博主上传文章:{articleName.text}");
subscribe(articleName.text); //向订阅的人员发送信息
}
}
}
3.新建两个PeopleA、PeopleB人员类,在里面声明Push推送消息方法,并且在strat里添加到订阅委托中
PeopleA:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//订阅人员A
public class PeopleA : MonoBehaviour
{
void Start()
{
Blogger.subscribe += Push; //向订阅委托中添加人员A的推送方法
}
//推送信息
void Push(string name)
{
Debug.Log($"我是人员A,接收到博主最新文章:{name}");
}
}
PeopleB:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//订阅人员B
public class PeopleB : MonoBehaviour
{
void Start()
{
Blogger.subscribe += Push; //向订阅委托中添加人员A的推送方法
}
//推送信息
void Push(string name)
{
Debug.Log($"我是人员B,接收到博主最新文章:{name}");
}
}
在Unity中,我们除了可以自定义委托类型来定义委托,我们还可以使用C#类库,为我们已经准备好的两个内置委托类型(Action
和Func
)来定义委托,它可以帮我们省去声明委托的这个步骤。它们都是泛型
的委托,Action是一个不返回任何值的委托类型,而Func是一个具有返回值的委托类型。
要想使用【Action委托】或者【Func委托】,首先我们需要入
System
名称空间才能使用
Action委托表示一个不返回值
的方法,并且可以接受从0到16个参数。通过使用Action委托,可以定义并传递不同参数类型的方法。例如:
using UnityEngine;
using System;
public class Example : MonoBehaviour
{
// 定义一个Action委托,它没有返回值
private Action<int> myAction;
private void Start()
{
myAction += PrintNumber1;
myAction += PrintNumber2;
myAction(5);
}
private void PrintNumber1(int number)
{
Debug.Log(number);
}
private void PrintNumber2(int number)
{
Debug.Log(number+1);
}
}
Func委托表示一个具有返回值
的方法,并且可以接受从0到16个参数。与Action委托不同,Func委托要求指定最后一个泛型参数
作为返回类型
。以下是一个示例:
using UnityEngine;
using System;
public class Example : MonoBehaviour
{
// 定义一个Func委托,它接受一个int类型的参数并返回一个字符串
private Func<int, string> myFunc;
private void Start()
{
myFunc = AddOneToString;
string result = myFunc(10);
Debug.Log(result); // 输出 "11"
}
private string AddOneToString(int number)
{
return (number + 1).ToString();
}
}
如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦
好了,我是向宇,https://xiangyu.blog.csdn.net/
一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你有任何问题,欢迎你来评论私信告诉我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~