Unity程序开发框架——事件中心模块

1. 场景与脚本设置
  • 场景描述:怪物死亡后,玩家脚本执行信息,任务脚本执行信息,以及执行其他信息。新建Monster Player Task Other四个脚本。

Monster脚本


public class Monster : MonoBehaviour
{
    public string sname = "怪物x";
    // Start is called before the first frame update
    void Start()
    {
        Dead();
    }
    void Dead()
    {
        Debug.Log("怪物死亡!");

        GameObject.Find("Player").GetComponent<Player>().MonsterDead(this);
        GameObject.Find("Task").GetComponent<Task>().TaskmonsterDead(this);
        GameObject.Find("Other").GetComponent<Other>().OthermonsterDead(this);

    }
}

Player脚本

public class Player : MonoBehaviour
{
    public void MonsterDead(Object info) {
        Debug.Log("玩家得奖励!"+(info as Monster).sname);
    }
}

Task脚本

public class Task : MonoBehaviour
{
    public void TaskmonsterDead(Object info)
    {
        Debug.Log("任务信息!" + (info as Monster).sname);
    }
}

Other脚本

public class Other : MonoBehaviour
{
    public void OthermonsterDead(Object info)
    {
        Debug.Log("做其他工作!" + (info as Monster).sname);
    }
}

  • 脚本挂载,分别挂载对应的游戏物体上。
    在这里插入图片描述
  • 运行测试
    在这里插入图片描述
    此种写法增加了脚本之间的耦合度,随着业务逻辑的复杂增加,导致逻辑不清维护难度增大。
2. 引入观察者模式
观察者模式简介
  • 模式的定义与特点
    观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
  • 观察者模式是一种对象行为型模式,其主要优点如下。
    降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
    目标与观察者之间建立了一套触发机制。
  • 它的主要缺点如下。
    目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
    当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
3.改写脚本
  • 事件中心脚本EventCenter
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;


public interface IEventInfo
{

}

public class EventInfo<T> : IEventInfo
{
    public UnityAction<T> actions;

    public EventInfo( UnityAction<T> action)
    {
        actions += action;
    }
}

public class EventInfo : IEventInfo
{
    public UnityAction actions;

    public EventInfo(UnityAction action)
    {
        actions += action;
    }
}


/// <summary>
/// 事件中心 单例模式对象
/// 1.Dictionary
/// 2.委托
/// 3.观察者设计模式
/// 4.泛型
/// </summary>
public class EventCenter : BaseManager<EventCenter>
{
    //key —— 事件的名字(比如:怪物死亡,玩家死亡,通关 等等)
    //value —— 对应的是 监听这个事件 对应的委托函数们
    private Dictionary<string, IEventInfo> eventDic = new Dictionary<string, IEventInfo>();

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

    /// <summary>
    /// 监听不需要参数传递的事件
    /// </summary>
    /// <param name="name"></param>
    /// <param name="action"></param>
    public void AddEventListener(string name, UnityAction action)
    {
        //有没有对应的事件监听
        //有的情况
        if (eventDic.ContainsKey(name))
        {
            (eventDic[name] as EventInfo).actions += action;
        }
        //没有的情况
        else
        {
            eventDic.Add(name, new EventInfo(action));
        }
    }


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

    /// <summary>
    /// 移除不需要参数的事件
    /// </summary>
    /// <param name="name"></param>
    /// <param name="action"></param>
    public void RemoveEventListener(string name, UnityAction action)
    {
        if (eventDic.ContainsKey(name))
            (eventDic[name] as EventInfo).actions -= action;
    }

    /// <summary>
    /// 事件触发
    /// </summary>
    /// <param name="name">哪一个名字的事件触发了</param>
    public void EventTrigger<T>(string name, T info)
    {
        //有没有对应的事件监听
        //有的情况
        if (eventDic.ContainsKey(name))
        {
            //eventDic[name]();
            if((eventDic[name] as EventInfo<T>).actions != null)
                (eventDic[name] as EventInfo<T>).actions.Invoke(info);
            //eventDic[name].Invoke(info);
        }
    }

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

    /// <summary>
    /// 清空事件中心
    /// 主要用在 场景切换时
    /// </summary>
    public void Clear()
    {
        eventDic.Clear();
    }
}
	通过观察者模式实现事件的注册与更改通知各个具体观察者进行自身状态的更新。
	降低了目标与观察者之间的耦合关系。
	通过实现泛型接口避免了频繁的装箱拆箱操作。
  • 修改Monster
public class Monster : MonoBehaviour
{
    public string sname = "怪物x";
    // Start is called before the first frame update
    void Start()
    {
       Invoke("Dead",1);
    }
    void Dead()
    {
        Debug.Log("怪物死亡!");

        //GameObject.Find("Player").GetComponent<Player>().MonsterDead(this);
        //GameObject.Find("Task").GetComponent<Task>().TaskmonsterDead(this);
        //GameObject.Find("Other").GetComponent<Other>().OthermonsterDead(this);
        EventCenter.GetInstance().EventTrigger("MonsterDead",this);

    }
}
  • 修改Player

public class Player : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        EventCenter.GetInstance().AddEventListener<Monster>("MonsterDead", (o) => {
            MonsterDead(o);
        });
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void MonsterDead(Object info) {

        Debug.Log("玩家得奖励!"+(info as Monster).sname);
    }
}

  • 修改Task
public class Task : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        EventCenter.GetInstance().AddEventListener<Monster>("MonsterDead", (o)=> {
            TaskmonsterDead(o);
        });
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    public void TaskmonsterDead(Object info)
    {
        Debug.Log("任务信息!" + (info as Monster).sname);
    }
}
  • 修改Other
public class Other : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        EventCenter.GetInstance().AddEventListener<Monster>("MonsterDead", (o) => {
            OthermonsterDead(o);
        });
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    public void OthermonsterDead(Object info)
    {

        Debug.Log("做其他工作!" + (info as Monster).sname);
    }
}

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yxlalm

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

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

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

打赏作者

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

抵扣说明:

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

余额充值