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#基础(十)委托与事件 -> 正文阅读

[游戏开发]【Unity游戏开发】C#基础(十)委托与事件

前言

本教程参考菜鸟教程,本人也是依赖菜鸟教程学习的C# 当你已经有其他的编程经验的时候,你再去学习别的语言,我觉得菜鸟教程是个不错的选择,你只需要把语言基础看完,然后就可以放心的去实战了,个中的语言细节是教不会的,需要你自己去实践

委托与事件

1. 委托

委托就是一个函数模板,或者你也可以理解为是一个变量,不同的是一般的变量是存储值的,而委托存储的是方法。

在你需要使用某个方法的时候,就可以通过委托调用。

1.1 委托的定义和简单使用

在C#中,委托是使用delegate来定义的,它看起来像一个虚方法,但是却不是。

委托的定义格式:

delegate 返回类型 委托名();//委托明遵循变量名定义规则

在简单的使用就是需要声明委托,赋值,再使用

using System;
namespace HelloWorldApplication
{
    class HelloWorld
    {
		public delegate int OneNum(int a);//定义一个委托,表示只能给这个委托赋值的方法的返回值是int类型,有一个int类型的参数
		private static int DoubleNum(int a)
		{
			//这个方法是让指定的数字变成二倍,随便定义的
			return a*2;
		}
        static void Main(string[] args)
        {
            //声明
			OneNum oneNum = null;
			//赋值
			oneNum = DoubleNum;
			//或者直接声明+赋值
			//OneNum oneNum = DoubleNum;
			//或者
			//OneNum oneNum = new OneNum(DoubleNum);
			//使用
			Console.WriteLine(oneNum(10));
        }
    }
}

输出的结果就是:20

1.2 Action和Func

Action和Func是系统已经定义好的委托,能够让我们来随意调用,是使用泛型来定义的,能够支持我们大部分使用委托的场景。

区别是,Action是返回值为void,里面有n个参数,使用重载的方法来定义n个参数,到目前为止,最多能有16个参数,足够我们去使用了。

而Func是具有返回类型,n个参数的委托。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Action和Func
{
    internal class Action和Func
    {
        //为使用Action创建的方法
        static void NullPar()
        {
            Console.WriteLine("没有参数的方法");
        }
        static void OnePar(int a)
        {
            Console.WriteLine("只有一个参数的方法:" + a);
        }
        static void TwoPar(int a, int b)
        {
            Console.WriteLine("具有两个参数的方法:" + a + b);
        }
        //为使用Func创建的方法
        static int OneNum(int a)
        {
            return a * 2;
        }
        static float TwoNum(int a, float b)
        {
            return a / b;
        }
        static void Main(string[] args)
        {
            Action nullPar = NullPar;
            Action<int> onePar = OnePar;
            Action<int, int> twoPar = TwoPar;
            
            Func<int,int> oneNum = OneNum;
            Func<int,float,float> twoNum = TwoNum;

            nullPar();
            onePar(10);
            twoPar(10, 20);

            Console.WriteLine("数的二倍:" + oneNum(10));
            Console.WriteLine("两数相除:" + twoNum(10, 2.5f));

        }
    }
}

1.3 多播委托

委托分为多播委托和单播委托,单播委托就是我们上面所说的,里面只含有一个方法,所以我们通过委托调用的时候,也是只调用那一个方法。

而多播委托其实就是一个方法集合,放你调用多播委托的时候,就会将多播委托这个集合遍历,挨个调用里面的方法。

其实单播委托也可以看成是只有一个成员的多播委托。

使用多播委托的方法就是:委托变量 += 方法;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Action和Func
{
    internal class MoreActiion
    {
        static void Test1()
        {
            Console.WriteLine("Test1");
        }
        static void Test2()
        {
            Console.WriteLine("Test2");
        }
        static void Main(string[] args)
        {
            Action action = null;
            action += Test1;//也可以action = Test1;但是最好使用+=。
            action += Test2;
            action();
        }
    }
}

就是这样使用。

多播委托最好使用返回类型为void的,因为多播委托只能返回最后一个方法的返回类型。

而将方法从多播委托中移除的方法就是使用-=符号。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Action和Func
{
    internal class MoreActiion
    {
        static void Test1()
        {
            Console.WriteLine("Test1");
        }
        static void Test2()
        {
            Console.WriteLine("Test2");
        }
        static void Main(string[] args)
        {
            Action action = Test1;
            action += Test2;
            Console.WriteLine("未移除时:");
            action();
            Console.WriteLine("移除后:");
            action -= Test1;
            action();
        }
    }
}

2. 事件

事件用通俗的话说就是:

当某个条件发生时,该干什么事。

在Unity中比较常见的有:鼠标点击事件,键盘点击事件等。

而事件其实本质上也是一种委托,所以在使用事件的时候其实也是使用委托。

在C#中使用事件的关键词是:event

event是用在声明委托变量时,写在委托类型的前面,下面看这个例子

public delegate void ATest();//定义一个委托
public static event ATest aTest;//声明一个事件,也是委托变量,区别就在于even关键字

在学习过委托后我们知道,使用委托需要给委托变量进行赋值,使用=号来进行赋值。

而如果是事件的话,就不能使用=号来赋值了,因为事件重写了=号的权限为private,是为了代码安全性,防止对事件本身进行操作。

只能使用+=来添加方法,-=来取消方法;重写了+=-=,其实这两个就是AddRemove方法,权限为public

当然,事件也是可以多播的。

Unity例子理解

例如一个游戏中,玩家死亡时要干的事就有这些:

  1. UI界面中将hp降低为0
  2. 播放玩家死亡动画
  3. 播放玩家死亡音效
  4. 怪物/敌人无法攻击或者停止攻击

而如果我们在每个地方都定义一个方法,在玩家死亡后挨个调用,就会破坏代码的高内聚低耦合。

而如果我们使用事件,就只需要在玩家内部声明一个事件,然后只调用这个事件即可。

为了更好的理解事件,我们来举个例子,为了简化流程,我就只写玩家,UI脚本了,当然在此之前我们还应该创建一个Unity项目,创建出玩家和UI。

1. 创建场景

在一个新的Unity项目中,我们使用一个Plane来当做地板,颜色就随便搞一下,或者不搞,就不细细说了。

在这里插入图片描述

好了,完事了,一个简单的场景+玩家+UI就完事了,那么开始敲代码吧!

2. 编写脚本

就随便写写好了。

  1. 玩家脚本(记得托给玩家哦)
/**
 * ==========================================
 * FileName:#FileName#
 * Author:#Name#
 * CreatTime:#CreateTime#
 * NowPath:#path#
 * ==========================================
 */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    public float hp;
    public delegate void Dead();
    public static event Dead Death;
    // Start is called before the first frame update
    void Start()
    {
        hp = 100;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            hp = 0;
            Death();
        }
    }
}
  1. UI脚本
/**
 * ==========================================
 * FileName:#FileName#
 * Author:#Name#
 * CreatTime:#CreateTime#
 * NowPath:#path#
 * ==========================================
 */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//引用UI

public class UI : MonoBehaviour
{
    Text hpText;
    float hp;
    // Start is called before the first frame update
    void Start()
    {
        hpText = GameObject.Find("Hp").GetComponent<Text>();
        hpText.text = "100";
    }
    private void OnEnable()
    {
        Player.Death += HpFor0;
    }
    // Update is called once per frame
    void HpFor0()
    {
        hpText.text = hp.ToString();
    }
    
}

3. 效果展示

好了看看效果:

在这里插入图片描述

当然,你可以记住这句话:使用事件是为了代码安全性,使用委托是为了低耦合高内聚,当然事件也是特殊的委托。

结语

成功的光彩靓丽之后是廉价的泪水和眼泪

欢迎喜爱Python,Unity(游戏开发引擎)的爱好者,让我们一步步走向大神,成功离得不远,也就两个字,坚持罢了!!

Unity游戏引擎宣言:

你是否热爱游戏呢?

你是否曾经幻想着有一天自己做出一款属于自己的游戏呢?

不要犹豫了,赶快学习吧!

点击链接查看Python社区:Python交流社区

点击链接查看Unity社区:游戏开发爱好者

  游戏开发 最新文章
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-05-11 16:43:30  更:2022-05-11 16:43:59 
 
开发: 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/23 11:07:58-

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