Unity设计模式之观察者模式

  在平常玩游戏的时候会遇到这种情况,以简单的Rpg举例。 勇者击杀了怪物,怪物死了,勇者摆出胜利姿势,系统提示怪物死亡 。如果按照一般逻辑可能会在怪物死亡的方法中去获取Player、Dialog,这样看上去其实也不太难。但如果需要去关联的事件很多,就需要在类中去获取各种各样的对象,非常麻烦而且也会使程序耦合性变高,这时就需要使用到观察者模式。

  观察者模式其本质就是通过委托将各个类中的方法都关联到一个固定的类上去,由该管理类去统一决定是否调用。由于很像是管理类去观察着各个类的情况,所以我们管这种设计模式叫做观察者模式,下面是观察者模式的简单实现。

  首先我们假定有三个对象分别是勇者(Player)、怪物(Monster)、提示框(Dialog)

 

public class Dialog : MonoBehaviour
{
    private void DialogSay(object info) {
        Debug.Log("叮咚!怪物已经寄了!");
    }
}

public class Player : MonoBehaviour
{
    
    private void Victor(object info) {
        Debug.Log("玩家摆出胜利姿势");
    }      
}
public class Monster : MonoBehaviour
{
    
    private void Start()
    {
        Dead();
    }
}

其中各自的类有各自的方法,完成不同的事情。

接下来使用统一的管理类起个名字叫做事件中心,代码如下

public class EventCenter : ISingleton
    {
        public static EventCenter Instance => Singleton<EventCenter>.Instace;

        /// <summary>
        /// 事件容器
        /// </summary>
        private Dictionary<string,UnityAction<object>> eventDic=new Dictionary<string, UnityAction<object>>();
        public void Init()
        {

        }

        /// <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>
        public void EventTrigger(string name,object info) {
            if (eventDic.ContainsKey(name))
            {
                eventDic[name].Invoke(info);
            }
        }

        /// <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>
        public void Clear() { 
            eventDic.Clear();
        }
    }

事件中心里,首先是有一个Dict事件容器Dictionary<string,UnityAction<object>>,用于存放各类事件,字典的键是事件的名字、值该事件委托。然后为了能够使在挂载事件的时候也能进行参数的传递,使用了泛型委托。然后中心对外提供四个方法,添加事件 AddEventListener、移除事件RemoveEventListener、事件触发器EventTrigge以及清空事件Clear。整个程序流程基本是,发生了某件事情,然后事件中心告知各个类对这个事件的响应。所以需要让各个类与事件中心关联起来。代码入下

    public class Player : MonoBehaviour
{
    private void Start()
    {
        EventCenter.Instance.AddEventListener("MonsterDie", Victor);
    }
    private void Victor(object info) {
        if (diedMonsterType == 1)
        {
            Debug.Log("死的是史莱姆");
        }
        Debug.Log("玩家摆出胜利姿势");
    }

    private void OnDestroy()
    {
        EventCenter.Instance.RemoveEventListener("MonsterDie", Victor);
    }             
}
    public class Dialog : MonoBehaviour
{
    private void Start()
    {
        EventCenter.Instance.AddEventListener("MonsterDie", DialogSay);
    }

    private void DialogSay(object info) {
        Debug.Log("叮咚!怪物已经寄了!");
    }
}
    public class Monster : MonoBehaviour
{
    /// <summary>
    /// 怪物类型(转发事件时参数的传递)
    /// </summary>
    public int monsterType = 1;
    private void Start()
    {
        Dead();
    }

    public void Dead()
    {
        Debug.Log("怪物已经死了");
        EventCenter.Instance.EventTrigger("MonsterDie",this.monsterType);
    }

}

当Monster被挂载到游戏对象上,游戏运行Start函数被调用,执行Dead方法,打印出“怪物已经死了”,然后事件中心触发名为“MonsterDie”事件并传入monsterType怪物类型,事件中心根据字典中的委托调用各个应该响应类中的函数。并且将monsterType作为参数传递到各个函数中,让响应类能够针对type不同做出判断,最终打印。

 以上就是观察者模式的简单实现。

  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值