博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Unity中使用委托/事件实现GameObject之间的通信
阅读量:2504 次
发布时间:2019-05-11

本文共 3769 字,大约阅读时间需要 12 分钟。

为什么GameObject之间需要通信?

  游戏开放中我经常遇到这样的问题,游戏中发生一个事件,我们如何把这个事件通知给其他的游戏物体,比如游戏中发生了爆炸,我们需要在一定范围内的GameObject都能感知到这一事件。

  有一种方法是将对该事件感兴趣的GameObject当做成员变量保存在触发该事件的GameObject的脚本组件里,那么我们把发生事件的GameObject当作Subject(被观察者),把对该事件感兴趣的GameObject当作Observer(观察者)。但这样做有个明显的缺点一旦增加一个Observer就需要修改Subject的代码,如果Observer移除了,还必须从Subject中移除这个成员变量。
  所以我们引入c#内置的一个非常棒的事件/委托机制,这可以让我们非常方便的使用观察者模式。

如果你还不了解观察者模式或事件/委托机制,请查阅相关资料。

常见的委托类型

// 该委托不传任何参数public delegate void CallFunc();// 该委托会传入发生事件的GameObject,即senderpublic delegate void CallFuncO(GameObject sender);// 该委托会传入发生事件的GameObject,即sender。和一个变长参数列表public delegate void CallFuncOP(GameObject sender, EventArgs args);

下面我将使用三种类型的委托实现游戏中简单的事件机制。

c#提供的一种标准委托类型

//标准委托类型public delegate void EventHandler(object sender, EventArgs e);//带泛型的委托类型public delegate void EventHandler
(object sender, TEventArgs e);

第二个参数是从EventArgs派生出的类型,用来保存事件的内容。

实现简单的事件机制

  • 创建GameEventArgs类,它继承EventArgs
public class GameEventArgs : EventArgs {    ///     /// 消息内容字典    /// key为消息内容的某个字段,value为字段的内容    ///     private Dictionary
_messageDic; public Dictionary
messageDic { get { return _messageDic; } } ///
/// 构造函数 /// public GameEventArgs() { _messageDic = new Dictionary
(); }}
  • ** 创建EventManager类,用于注册和发送事件,仅仅实现了注册和发送方法
/// /// 消息处理委托/// /// /// public delegate void onMessageArrived(object obj,GameEventArgs args);/// /// 消息管理类/// public class EventManager{    ///     /// 单例消息管理    ///     private static EventManager _instance;    public static EventManager instance    {        get        {            if(_instance == null)            {                _instance = new EventManager();            }            return _instance;        }    }    ///     /// 消息字典,key为消息名称,onMessageArrived为处理消息的委托    ///     private Dictionary
eventListeners; private EventManager() { eventListeners = new Dictionary
(); } ///
/// 注册事件 /// ///
事件名 ///
事件处理委托 public void addEventListener(string key, onMessageArrived listener) { if(eventListeners.ContainsKey(key)) { return; } eventListeners.Add(key, listener); } ///
/// 事件分发 /// ///
事件名 ///
发送者 ///
发送内容 public void dispatchEvent(string key, Object obj, GameEventArgs args) { if(eventListeners.ContainsKey(key)) { eventListeners[key](obj, args); } }}
  • 一个简单的示例
    在场景中创建两个GameObject,分别为cube和sphere,如下图:
    这里写图片描述
    分别为cube和sphere添加脚本组件Cube.cs和Sphere.cs.
public class Cube : MonoBehaviour {    private Sequence mySequence;    // Use this for initialization    void Start () {        mySequence = DOTween.Sequence();        mySequence.Append(gameObject.transform.DOMoveX(5, 2, false).SetRelative());        mySequence.OnComplete(new TweenCallback(() =>        {            GameEventArgs eventArgs = new GameEventArgs();            eventArgs.messageDic.Add("jumpTimes", 5);            EventManager.instance.dispatchEvent("jump", this, eventArgs);        }));        mySequence.Pause();        StartCoroutine(move());    }    IEnumerator move()    {        yield return new WaitForSeconds(2.0f);        mySequence.Play();    }}
public class Sphere : MonoBehaviour {    // Use this for initialization    void Start () {        EventManager.instance.addEventListener("jump", new onMessageArrived(jump));    }    private void jump(object obj, GameEventArgs args)    {        if(args.messageDic.ContainsKey("jumpTimes"))        {            gameObject.transform.DOJump(new Vector3(0, 3, 0), 1, Convert.ToInt32(args.messageDic["jumpTimes"]), 2).SetRelative();        }    }}

这两段代码很简单,游戏物体cube移动一段距离后发出名称为”jump”的事件,游戏物体Sphere注册了”jump”事件,当Sphere收到事件后,执行jump动作。

你可能感兴趣的文章
Neutron在给虚拟机分配网络时,底层是如何实现的?
查看>>
netfilter/iptables全攻略
查看>>
Overlay之VXLAN架构
查看>>
Eclipse : An error occurred while filtering resources(Maven错误提示)
查看>>
在eclipse上用tomcat部署项目404解决方案
查看>>
web.xml 配置中classpath: 与classpath*:的区别
查看>>
suse如何修改ssh端口为2222?
查看>>
详细理解“>/dev/null 2>&1”
查看>>
suse如何创建定时任务?
查看>>
suse搭建ftp服务器方法
查看>>
centos虚拟机设置共享文件夹并通过我的电脑访问[增加smbd端口修改]
查看>>
文件拷贝(IFileOperation::CopyItem)
查看>>
MapReduce的 Speculative Execution机制
查看>>
大数据学习之路------借助HDP SANDBOX开始学习
查看>>
Hadoop基础学习:基于Hortonworks HDP
查看>>
为什么linux安装程序 都要放到/usr/local目录下
查看>>
Hive安装前扫盲之Derby和Metastore
查看>>
永久修改PATH环境变量的几种办法
查看>>
大数据学习之HDP SANDBOX开始学习
查看>>
Hive Beeline使用
查看>>