Unity开发之观察者模式(事件中心)

观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在观察者模式中,主体是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。

一、事件中心管理类

继承了一个单例模式基类,节省代码

cs 复制代码
public class EventCenter : BaseManager<EventCenter>
{
    //key ------ 事件的名字(比如:怪物死亡,玩家死亡,通关 等等)
    //value ------ 对应的是 监听这个事件 对应的委托函数们
    private Dictionary<string, UnityAction<object>> eventDic = new Dictionary<string, UnityAction<object>>();

    /// <summary>
    /// 添加事件监听
    /// </summary>
    /// <param name="name">事件的名字</param>
    /// <param name="action">准备用来处理事件 的委托函数</param>
    public void AddEventListener(string name, UnityAction<object> action)
    {
        //有没有对应的事件监听
        //有的情况
        if( eventDic.ContainsKey(name) )
        {
            eventDic[name]+= action;
        }
        //没有的情况
        else
        {
            eventDic.Add(name, action);
        }
    }

    /// <summary>
    /// 过场景,移除对应的事件监听
    /// </summary>
    /// <param name="name">事件的名字</param>
    /// <param name="action">对应之前添加的委托函数</param>
    public void RemoveEventListener(string name, UnityAction<object> action)
    {
        if (eventDic.ContainsKey(name))
            eventDic[name]-= action;
    }

    /// <summary>
    /// 事件触发
    /// </summary>
    /// <param name="name"></param>
    public void EventTrigger(string name,object info)
    {
        //有没有对应的事件监听
        //有的情况
        if (eventDic.ContainsKey(name))
        {
            if (eventDic[name]!= null)
                eventDic[name].Invoke(info);
        }
    }

    /// <summary>
    /// 清空事件中心
    /// 主要用在 场景切换时
    /// </summary>
    public void Clear()
    {
        eventDic.Clear();
    }
}

二、模拟一个功能

玩家要完成一个任务"杀死三只哥布林",玩家点击鼠标左键杀死一只怪物,如果这个怪物是哥布林,那么任务计数加1,达到3后提示任务完成。

其中还会显示玩家击杀了什么怪物,击杀后获得多少金钱

玩家类

cs 复制代码
public class Player : MonoBehaviour
{
    public string name = "Holens";
    // Start is called before the first frame update
    void Start()
    {
        EventCenter.GetInstance().AddEventListener("MonsterDead", GetMoney);
    }

    // Update is called once per frame
    void Update()
    {
        //按下左键杀死哥布林
        if (Input.GetMouseButtonDown(0))
        {
            KillMonster();
        }
    }

    public void KillMonster()
    {
        //杀死哥布林
        //向事件中心发送请求 执行杀死哥布林逻辑
        EventCenter.GetInstance().EventTrigger("KillMonster", this);
    }
    public void GetMoney(object info)
    {
        print(this.name+"杀死了" + (info as Monster).name + "获得"+ (info as Monster).money+"金钱");
    }
}

怪物类

cs 复制代码
public class Monster : MonoBehaviour
{
    public string name;
    public int money = 100;
    // Start is called before the first frame update
    void Start()
    {
        //向 击杀哥布林 委托添加死亡函数
        EventCenter.GetInstance().AddEventListener("KillMonster", Dead);
    }

    public void Dead(object info)
    {
        print((info as Player).name+"杀死了"+this.name);
        //死亡时向事件中心发送请求 执行怪物死亡逻辑
        EventCenter.GetInstance().EventTrigger("MonsterDead", this);
    }
}

任务类

cs 复制代码
public class Task : MonoBehaviour
{
    public int nowNum;
    public int maxNum = 3;
    public string messionInfo = "杀死三只哥布林";
    public bool isFinish = false;
    // Start is called before the first frame update
    void Start()
    {
        print("任务目标是" + messionInfo);
        //怪物死亡
        //向 怪物死亡 委托添加函数(当怪物死亡时任务计数加1)
        EventCenter.GetInstance().AddEventListener("MonsterDead", UpdateNum);
    }

    // Update is called once per frame
    void Update()
    {
        if (nowNum == maxNum&&!isFinish)
        {
            //计数达到目标,任务完成
            FinishMession();
            isFinish = true;
        }
    }
    public void UpdateNum(object info)
    {
        //如果杀死的目标是哥布林,则计数增加
        if ((info as Monster).name=="哥布林")
        {
            nowNum++;
        }
    }
    public void FinishMession()
    {
        print("任务完成");
    }
}

三、运行过程及结果

创建三个物体并挂载相应代码

怪物名字设置成1

此时按下鼠标左键五次,可以看到触发了提示但是因为杀的不是哥布林,所以任务没有完成

将名字改为哥布林,点击三次后提示完成任务

相关推荐
小拉达不是臭老鼠1 小时前
Unity中的UI系统之UGUI
学习·ui·unity
万兴丶1 小时前
Coplay适用于 Unity 的“Al 代理”使用指南
unity·游戏引擎·ai编程
z落落1 小时前
C# 构造函数(无参/有参/重载/this)+析构函数(终结器)|GC 垃圾回收
java·开发语言·c#
z落落2 小时前
C# 字段与属性(get/set访问器、三种属性写法、只读属性)+属性拦截例子(get动态计算 + set数据校验)
开发语言·c#
影寂ldy2 小时前
C#栈和队列
开发语言·c#
魔法阵维护师2 小时前
从零开发游戏需要学习的c#模块,第三十四章(设置界面)
学习·游戏·c#
gc_22992 小时前
学习C#调用OpenXml操作word文档的基本用法(39:学习表格类-1)
c#·word·表格·table·openxml
gc_22993 小时前
C#测试调用Net.Codecrete.QrCodeGenerator库生成二维码的基本用法
c#·二维码·qrcodegenerator
魔士于安4 小时前
Unity材质球大合集
unity·游戏引擎·材质
yivifu4 小时前
CSS 自动级联编号有序列表完全指南
前端·css·c#·html·有序列表·级联编号