Unity事件管理器

一、前置知识:委托和事件

在C#中,委托是用来存储方法的容器,事件是更安全的委托。

委托:命名空间System中,包含了Action<>和Func<>两种泛型委托,Action<>委托存储无返回值的方法,Func<>委托存储有返回值的方法,存储后通过()或者.Invoke()调用里面的方法。

//使用系统自带的委托,使用时必须引用using System命名空间
Console.WriteLine("--系统委托Action--");//Action无返回值的委托
Action action = null;//Action委托无参数委托
action += Fun1;
action.Invoke();
Action<string,int> action2 = null;//Action泛型n个参数委托(n<=16)
action2 += Fun4;
action2.Invoke("nihao",123);
Console.WriteLine("--系统委托Func--");//Func泛型有返回值委托
Func<string> func = null;//Func泛型无参数sting返回值委托
func += Fun3;
Console.WriteLine(func.Invoke());
Func<int,int> func2 = null;//Func泛型前面参数,最后一个返回值
func2 += Fun2;
func2.Invoke(16);
//测试方法Fun
static public void Fun1()
{
	Console.WriteLine("void Fun1");
}
static public int Fun2(int value)
{
	Console.Write("int Fun2:{0}",value);
	return value;
}
static public string Fun3()
{
	return "string Fun3";
}
static public void Fun4(string s,int i)
{
	Console.WriteLine("void Fun4 string:{0},int:{1}",s,i);
}

以上是部分代码,更详细的语法可以参考C#委托和事件,匿名函数和lamabda表达式

事件:只能作为成员变量存在类,接口和结构体中,相比于委托,事件不能在类的外部赋值与调用

访问修饰符 event 委托类型 事件名,public event Action myEvent; ,和委托用法相同。

  • 为什么有事件

防止外部随意置空委托

防止外部随意调用委托

二、理解概念:观察者模式

当游戏的工程量大时,需要执行的代码散落在各个文件中,不方便管理,而且如果如果直接调用,那么代码的耦合性会大大增加,陷入"牵一发而动全身"的情况。

因此,为了更好地集中管理游戏中的事件,以及减少“获取各个类的事件前要先要持有该类的引用”操作,利用观察者模式这种思想编写一个事件管理脚本,来统一处理事件的注册,移除,发送等操作,将事件拥有者和事件响应者完全解耦。

观察者模式:

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。

举个例子,当游戏结束时(一个对象被修改),我们希望弹出结束UI,暂停播放音乐,结算总体分数等(通知依赖它的对象)。

一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

这种编程模式不仅考虑到了易用性和低耦合性,保证高度的协作性。

实现:观察者模式使用三个类 Subject、Observer 和 Client。

在这里插入图片描述

三、Unity中的事件管理

比如创建一个事件管理类,EventHandler.cs,相当于调度中心

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
//不用挂载到任何物体上,就不会有任何父类函数
public class EventHandler
{
    //比如希望游戏结束后执行相关方法,在其他脚本中添加方法到该事件中,然后调用CallGameOverEvent()静态函数
    //就可以执行游戏结束后的相关方法
    public static event Action GameOverEvent;
    public static void CallGameOverEvent()
    {
        GameOverEvent?.Invoke();//判断GameOverEvent事件不为空时执行里面的方法
    }
}

在需要使用其他脚本的方法时,通过注册事件和注销事件来进行

比如想要游戏结束时显示一个UI,UImanager.cs,相当于表现对象

private void OnEnable()//注册事件
{
    Time.timeScale = 1;//恢复游戏时间
    EventHandler.GameOverEvent += OnGameOverEvent;
}
private void OnDisable()//注销事件
{
    EventHandler.GameOverEvent -= OnGameOverEvent;
}
private void OnGameOverEvent()
{
   //启用一个物体
   gameOverPanel.SetActive(true);//显示游戏结束UI
   if(gameOverPanel.activeInHierarchy)
   {
      //一直触发时会判断该窗口是否为激活状态,如果是则游戏时间暂停
      Time.timeScale = 0;
   }
}

OnEnable()和OnDisable()与Updata(),Start()一样是周期函数,启用物体,生成物体都会运行OnEnable(),禁用物体,物体销毁会运行OnDisable()

在控制游戏结束的脚本中,调用CallGameOverEvent()方法,相当于改变者

EventHandler.CallGameOverEvent();//调用CallGameOverEvent()静态函数

可以发现,有了事件管理中心后,只需要在调度中心编写触发事件的代码。改变者和表现对象的代码改动不会影响另一方,事件的处理在底层上全交给了调度中心,这样对跨模块的交互起到很好的解耦作用。


学习过程中参考了以下内容,诚挚感谢知识的分享者!

菜鸟教程 | C# 教程

YY-nb|Unity 事件管理中心

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

睡不着乌托托

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值