Unity游戏开发(C#语法):委托

一.什么是委托

1.委托的概述

为了实现方法的参数化,提出了委托的概念。委托是一种类是一种引用类型,可以指向一个或者多个方法,该引用类型与其他引用类型不同。在委托对象的引用中存放的不是数据的引用,而是对方法的引用,即在委托的内部包含一个指向某个方法的指针。通过使用委托把方法的引用封装在委托对象中,然后将传递的给调用的引用方法的代码。这个委托类型的实例,可以和任何其他方法相关联起来,储存这些方法的引用只要类型兼容(类型兼容即任何方法他们的参数和返回值与委托的参数和返回值保持一致)。委托也是事件的本质,事件也是委托类型字段的包装器。

1.现实世界举例

拿现实世界举例子比如你在宿舍微信群发出,出去买饭快了回来的消息,而你的舍友们想要让你带饭,这就是一种委托。简而言之委托就是有一件事我不亲自做它,而是交给别人替我去做那些本该由我来做的事。我委托你干什么你就干什么,没有委托你你概不负责。

2.程序世界举例

拿游戏开发举例子,游戏结束你写了一个GameOver的方法你想让游戏结束后想让这个方法里实现些什么比如Player的经验增加,播放胜利动画,显示结束UI等功能。这个时候就可以通过委托的方法,定义一个委托类型Mydelegate通过Mydelegate订阅封装Player的经验增加,播放胜利动画,显示结束UI这几个方法,然后GameOver()直接调用Mydelegate();就好了直接实现了这3个功能,所以GameOver()可以不用直接调用这3个方法,可以通过委托间接调用

二.代码举例

此例子讲的是一个图片,通过按空格键实现此图片的颜色随机变化,位置随机变化,打印当前时间的3个功能。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;


//public delegate void Mydelegate();//保持类与类的平级关系
  public class Main : MonoBehaviour
{
    //声明委托类型
    public delegate void Mydelegate();//该委托类型可以指向任何一个返回值为空,参数列表为空的其他方法。
    //声明格式为:访问修饰符,  delegate ,与目标方法一致的返回值类型,委托名称,,与目标方法一致参数列表
    //【嵌套类型】

     Mydelegate mydelegate;
    

    private SpriteRenderer sp;


    private void OnEnable()
    {
        mydelegate = new Mydelegate(Teleport);//完整订阅格式
        mydelegate +=ChangeColor;//直接让变量引用方法
        mydelegate += log;//切记:只有第一个可以使赋值操作,之后的订阅必须是+=,不然的话之后的订阅会覆盖之前的赋值操作**
        //如果这个是=号他只会引用log,teleport就会被覆盖
       
      

    }
    void Start()
    {
        sp = GetComponent<SpriteRenderer>();
       
    }

  
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            //    Teleport();//直接调用
            //    ChangeColor();//直接调用
            //    log();//直接调用
            mydelegate();//在update调用mydelegate,间接调用3个方法
            // mydelegate.Invoke();//可以用Invoke()调用          
        }
    }

    //随机更换位置
    private void Teleport()
    {
        sp.color = new Color(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value);
    }
    //切换颜色
    private void ChangeColor()
    {
        Vector2 currentpos = transform.position;
        currentpos.x = UnityEngine.Random.Range(-5f, 5f);
        transform.position = currentpos;
    }
    //打印当前时间
    private void log()
    {
        Debug.Log("Current Time is:" + DateTime.Now);
    }
 

}


该代码的流程是
1.首先声明一个委托类型。
2.再声明一个委托类型的字段。
3.分别写好实现三个功能的方法。
4.在OnEnable()中实现委托的订阅(+=)直接让变量引用方法。
5.在Update()中调用订阅之后委托类型字段。
下面依次介绍主要步骤

三.委托的语法

1.声明格式

public delegate void Mydelegate(); 
//该委托类型可以指向任何一个返回值为空,参数列表为空的其他方法。

委托的声明和普通的类有一定区别,但跟方法确有些相似
声明格式为:访问修饰符, delegate ,与目标方法(所引用的方法)一致的返回值类型,委托名称,与目标方法一致参数列表

2.委托的订阅

1.单播委托

一个委托封装了一个方法的形式叫做【单播委托】

private void OnEnable()
    {
        mydelegate = new Mydelegate(Teleport);//完整订阅格式
        //mydelegate = Teleport;//简介订阅方式
      
    }

如图所示这个委托只封装了随机更换位置这一个方法,所以这就是单播委托
可以用=号进行赋值操作,也可以用+=订阅。

2.多播委托

一个委托封装的多个方法的使用形式叫做【多播委托】

private void OnEnable()
    {
        mydelegate = new Mydelegate(Teleport);//完整订阅格式
        mydelegate += ChangeColor;//直接让变量引用方法
        mydelegate += log;
        //切记:只有第一个可以使赋值操作,之后的订阅必须是+=,不然的话之后的订阅会覆盖之前的赋值操作
        //如果这个是=号他只会引用log,teleport就会被覆盖
     
     

    }

如图所示
1.多播委托就是我的变量订阅了多个方法,切记只有第一个可以使赋值操作,之后的订阅必须是+=,不然的话之后的订阅会覆盖之前的赋值操作,如果这个是=号他只会引用log,teleport就会被覆盖。
2.由于我声明的是无返回值,无参数列表的委托,所以我的委托只能订阅无返回值,无参数列表的方法,这就是类型兼容。

3.简单例子

解释都在注释中

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class delegate01 : MonoBehaviour
{
    public delegate int  Mydelegate_01(int n1, int n2);
    //该委托类型可以指向任何一个返回值为int类型,参数列表为两个int类型参数的其他方法。
    Mydelegate_01 mydelegate_01;
  
    
    private void OnEnable()
    {
        mydelegate_01 = Add;//订阅ADD方法
        mydelegate_01 += Mutiply;//订阅Mutiply方法
        //切记ADD 和 Mutiply也是返回值为int类型,参数列表为两个int类型参数的方法,保持类型兼容
      
    }


    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log(mydelegate_01(2, 3));
         
        }
    }

    public int Add(int a, int b)
    {
        Debug.Log(a + b);
        return a + b;
    }
    public int Mutiply(int  a,int  b)
    {
        Debug.Log(a * b);
        return a * b;
    }
   
}


image.png

四.Func<>委托和Action<>委托

Func<>委托和Action<>委托的本质其实还是Delegate,与Delegate的使用方法如出一辙

1.Func<>委托

1.Func<>一定能指向一个有返回值,可以有参数列表的方法(参数列表可以没有,但返回值必须有)
2.定义格式:例如Func<参数,参数,返回值类型> 括号的最后一个值永远是返回值(参数可以是多个,最多是16个跟Action相同。

举例

解释见注释

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class delegate01 : MonoBehaviour
{
    
    Func<int, int, int> func;//能指向一个返回值为int,和两个类型为int的参数的方法
    
    private void OnEnable()
    {
        
        func += Add;//订阅
        func += Mutiply;
    }


    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
           Debug.Log( func(2,3));
        }
    }

    public int Add(int a, int b)//与func类型兼容的方法
    {
        Debug.Log(a + b);
        return a + b;
    }
    public int Mutiply(int  a,int  b)//与func类型兼容的方法
    {
        Debug.Log(a * b);
        return a * b;
    }
  

}

V4O7U4)398QX{1LPDZP1U%U.png

2.Action<>委托

1.Action<>委托一定指向一个无返回值的方法,参数可有可无。
2.定义:因为Action没有返回值,所以括号里全是参数(也可以没有尖括号那就代表着没有参数)
Action action/Action<参数> action

举例
using System.Collections.Generic;
using UnityEngine;
using System;

public class delegate01 : MonoBehaviour
{
    
    Action<string> action;//能指向一个无返回值,和一个String类型的方法
  
    
    private void OnEnable()
    {
        
        action = SayHello;
    }


    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {          
            action.Invoke("Ben");
        }
    }

  
    public void SayHello(string name)
    {
        Debug.Log("Hello~" + name);
    }
}

五.常用用法

1.由于为了实现方法的参数化,提出了委托的概念,所以要将委托作为参数传递到方法中。所以引出了常用的作为模板方法和回调方法来使用。

1.模板方法

1.有一处不确定,其余代码都是固定写好的,这个不确定的部分(参数)就是靠我们传进来的委托类型
的参数所包含的方法来填补,就跟填空题一样。由于这个方法一般需要返回值,所以一般都用Func委托作为模板方法。

举例

描述:这个例子是为了实现输出玩家的夺旗数,死亡数和击杀数最高的玩家名称
1.首先这是玩家的基本信息类 里面包括了击杀数,夺旗数和死亡数的字段

image.png

2.第二部我们声明一个返回值为int类型,为PlayerStatus类型的,int类型返回值用于返回我们玩家击杀数等信息

image.png

3.创建以我们创建委托类型为参数的方法(string返回值用于返回玩家的名称),为什么种方法呢,因为这里的不确定的部分就是int tempnum = _delegate(player),通过该委托封装的方法返回的int值来代替int tempnum =,的后面的内容将player作为delegate的参数,然后进行下面的判断,

image.png
4.创建与委托类型兼容的方法,也就是返回击杀数等数值的方法,然后我们就可以将与委托类型类型兼容的方法来代替这个委托类型的参数(其实省略了创建委托字段,订阅方法的这两个步骤,直接代替即可)

image.png
image.png

5.补充:其实也可以用LAMBDA表达式匿名函数的方法来代替直接用方法代替参数的方法。这样的话直接省略了创建类型兼容方法的这步,减少了代码量。
LAMBDA表达式:(输入参数的参数名字)=>输出return 输出数值

image.png

6.利用这种委托最为参数的方法,来避免了如果计算更多的值,还得写更多的判断方法。减少了代码量。

2.回调方法

1.以回调方法的形式使用委托,根据逻辑,动态选择是否调用

举例

image.png

解释:该方法的参数有一个返回值为Product类型的Fuc<>委托和一个参数为Product类型的Action<>委托,将func委托的返回值赋给box.Product,如果func()的返回值的Price大于了5则将func返回的Product类型返回值,作为Action委托的参数使用。那如果func()的返回值的Price不大于5,那么永远也不会调用Action委托所以Action是通过内部逻辑才会调用的,所以这里的Action委托所封装的方法是作为回调方法使用的,则Func委托所封装的方法是作为模板方法使用的。

Unity 是一款流行的游戏引擎,它提供了丰富的开发工具和功能,可以用于开发各种类型的游戏和应用程序。 在 Unity 中,委托(Delegate)是一种重要的编程概念,它允许程序员将方法作为参数传递,并通过委托来调用这些方法。 在这个问题中,如果我们有一个委托叫做 greetpeople,我们可以使用 Unity 引擎的相关 API 来实现 greetpeople 这个委托。 首先,我们需要定义 greetpeople 的委托类型。可以使用以下代码: ``` public delegate void GreetPeopleDelegate(string name); ``` 接下来,我们可以编写一个方法作为 greetpeople 的实现,例如: ``` public void Greet(string name) { Debug.Log("Hello, " + name + "!"); } ``` 在这个例子中,我们简单地将传入的名字连接到问候语后面,并使用 Unity 引擎的 Debug.Log 函数输出结果。 最后,我们可以使用 greetpeople 委托来调用 Greet 方法。例如: ``` GreetPeopleDelegate greetpeople = Greet; greetpeople("Bob"); ``` 在这个示例中,我们将 Greet 方法赋值给 greetpeople 委托,并传入字符串 "Bob"。通过调用 greetpeople 委托,我们实际上会调用 Greet 方法,并输出 "Hello, Bob!" 到 Unity 编辑器的日志中。 通过使用 Unity 引擎的委托机制,我们可以更加灵活地设计和组织代码,实现各种功能和交互。无论是游戏开发还是其他应用程序开发委托都是非常有用的编程工具。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值