使用委托和事件在类之间传值

本文介绍了一个基于Unity的游戏事件系统实现方案,通过自定义EventDispatcher和EventListener类,利用C#的委托(delegate)机制实现了游戏对象间的事件传递和响应。
这里可能需要前期准备一下c#的委托(delegate)和事件(event)方面的知识了。。。
不是很明白的,就各种谷歌吧~
需要准备二个继承与MonoBehaviour的EventDispatcher类和EventListener类。
我这里吧delegate就写在EventDispatcher里了,也可以新建一个类吧这些delegate存在里面,方便一点。。。
  1. //定义委托事件,它定义了可以代表的方法的类型
            
            /**事件*/
            public delegate void EventHandler(GameObject e);  
            /**碰撞检测*/
            public delegate void CollisionHandler(GameObject e,Collision c);
            /**触发器检测*/
            public delegate void TriggerHandler(GameObject e,Collider other);
            /**控制器碰撞检测*/
            public delegate void ControllerColliderHitHandler(GameObject e,ControllerColliderHit hit);
            /**新关卡被加载进来*/
            public delegate void LevelWasLoadedHandler(GameObject e,int level);

委托定义好了,其实这些就类似于方法参数一样。。。可意会不好言传啊。。。

然后重写MonoBehaviour支持的那些时间响应函数:
比如OnMouseDown();
首先定义一个EventHandler 这个委托的事件。。。然后再OnMouseDown响应函数里对他进行操作。。
如果某个GameObject侦听了这个事件并写出了响应函数(响应函数即是定义事件的委托delegate),那么在重写的OnMouseDown函数类就会调用执行这个传进来的delegate并且把this.gameObject传出去。
  1. public event EventHandler MouseDown;  
            void OnMouseDown(){  
                    if (MouseDown != null)  
                            MouseDown (this.gameObject); 
            }


复制代码


以此类推,附上EventDispatcher类:
  1. using System;
    using UnityEngine;  
    /**  
    *  基于MonoBehaviour的一个事件派发类 
    * A simple event dispatcher - allows to listen to events in one GameObject from another GameObject
    * 
    * 
    *  Usage: 
    *  Add this script to the object that is supposed to dispatch events.  
    *  In another objects follow this pattern to register as listener at intercept events:
      
        void Start () { 
            EventDispatcher ev = GameObject.Find("someObject").GetComponent<EventDispatcher>();
            ev.MouseDown += ListeningFunction; // Register the listener (and experience the beauty of overloaded operators!)
        } 
    
        void ListeningFunction (GameObject e) { 
            e.transform.Rotate(20, 0, 0); // 'e' is the game object that dispatched the event
            e.GetComponent<EventDispatcher>().MouseDown -= ListeningFunction; // Remove the listener
        } 
         
    *  This class does not implement all standards events, nor does it allow dispatching custom events,  
    *  but you shold have no problem adding all the other methods. 
    * 
    * date: 2013.8.21
    */  
    public class EventDispatcher:MonoBehaviour{
            
            //定义委托事件,它定义了可以代表的方法的类型
            
            /**事件*/
            public delegate void EventHandler(GameObject e);  
            /**碰撞检测*/
            public delegate void CollisionHandler(GameObject e,Collision c);
            /**触发器检测*/
            public delegate void TriggerHandler(GameObject e,Collider other);
            /**控制器碰撞检测*/
            public delegate void ControllerColliderHitHandler(GameObject e,ControllerColliderHit hit);
            /**新关卡被加载进来*/
            public delegate void LevelWasLoadedHandler(GameObject e,int level);
                     
            
            
            
            public event EventHandler MouseEnter;  
            void OnMouseEnter(){  
                    if (MouseEnter != null)  //如果有方法注册委托变量
                            MouseEnter(this.gameObject); //通过委托调用方法
            }
            
            public event EventHandler MouseOver;
            void OnMouseOver(){  
                    if (MouseOver != null)  
                            MouseOver (this.gameObject); 
            }
            
            public event EventHandler MouseExit;  
            void OnMouseExit(){  
                    if (MouseExit != null)  
                            MouseExit (this.gameObject); 
            }
            
            public event EventHandler MouseDown;  
            void OnMouseDown(){  
                    if (MouseDown != null)  
                            MouseDown (this.gameObject); 
            }
            
            public event EventHandler MouseUp;  
            void OnMouseUp(){  
                    if (MouseUp != null)  
                            MouseUp (this.gameObject); 
            }
            
            public event EventHandler MouseDrag;  
            void OnMouseDrag(){  
                    if (MouseDrag != null)  
                            MouseDrag (this.gameObject); 
            }
            
            /**当renderer(渲染器)在任何相机上可见时调用OnBecameVisible*/
            public event EventHandler BecameVisible;  
            void OnBecameVisible (){  
                    if (BecameVisible != null)  
                            BecameVisible (this.gameObject);  
            }  
            /**当renderer(渲染器)在任何相机上都不可见时调用OnBecameInvisible*/
            public event EventHandler BecameInvisible;  
            void OnBecameInvisible (){  
                    if (BecameInvisible != null)  
                            BecameInvisible (this.gameObject);  
            }  
            public event EventHandler Enable;
            void OnEnable(){
                    if(Enable != null)
                            Enable(this.gameObject);
            }
            public event EventHandler Disable;
            void OnDisable(){
                    if(Disable != null)        
                            Disable(this.gameObject);
            }
             public event EventHandler Destroy;
            void OnDestroy(){
                    if(Destroy != null)
                            Destroy(this.gameObject);
            }
            /**在相机渲染场景之前调用*/
            public event EventHandler PreRender;
            void OnPreRender(){
                    if(PreRender != null)
                            PreRender(this.gameObject);
            }
            /**在相机完成场景渲染之后调用*/
            public event EventHandler PostRender; 
            void OnPostRender(){
                    if(PostRender != null)
                            PostRender(this.gameObject);
            }
            /**在相机场景渲染完成后被调用*/
            public event EventHandler RenderObject; 
            void OnRenderObject(){
                    if(RenderObject != null)
                            RenderObject(this.gameObject);
            }
            
    
            
            public event EventHandler ApplicationPause; 
            void OnApplicationPause(){
                    if(ApplicationPause != null)
                            ApplicationPause(this.gameObject);
            }
            /**当玩家获得或失去焦点时发送给所有游戏物体*/
            public event EventHandler ApplicationFocus; 
            void OnApplicationFocus(){
                    if(ApplicationFocus != null)
                            ApplicationFocus(this.gameObject);
            }
            public event EventHandler ApplicationQuit; 
            void OnApplicationQuit(){
                    if(ApplicationQuit != null)
                            ApplicationQuit(this.gameObject);
            }
            
            
            
            public event TriggerHandler TriggerEnter;
            void OnTriggerEnter(Collider other){
                    if(TriggerEnter != null)
                            TriggerEnter(this.gameObject,other);
            }
            public event TriggerHandler TriggerExit;
            void OnTriggerExit(Collider other){
                    if(TriggerExit != null)
                            TriggerExit(this.gameObject,other);
            }
            public event TriggerHandler TriggerStay;
            void OnTriggerStay(Collider other){
                    if(TriggerStay != null)
                            TriggerStay(this.gameObject,other);
            }
            
            public event ControllerColliderHitHandler controllerColliderHit;
              void OnControllerColliderHit(ControllerColliderHit hit){
                    if(controllerColliderHit != null)
                            controllerColliderHit(this.gameObject,hit);
            }
            
        public event CollisionHandler CollisionEnter;  
        void OnCollisionEnter (Collision c){  
            if (CollisionEnter != null)  
                CollisionEnter (this.gameObject, c);  
        }  
             public event CollisionHandler CollisionStay;  
        void OnCollisionStay (Collision c){  
            if (CollisionStay != null)  
                CollisionStay (this.gameObject, c);  
        }  
            
        public event CollisionHandler CollisionExit;  
        void OnCollisionExit (Collision c){  
            if (CollisionExit != null)  
                CollisionExit (this.gameObject, c);  
        }
            
            public event LevelWasLoadedHandler LevelWasLoaded;
            void OnLevelWasLoaded(int level){
                    if(LevelWasLoaded != null)
                            LevelWasLoaded(this.gameObject,level);
            }
    }  

写好了派发事件的类拖到需要派发事件出来的组件上,然后再来注册和侦听吧,下面写出EventListener类做出侦听的步骤。。
首先需要获取目标组件上的EventDispatcher组件。
  1. private EventDispatcher evt = null;
            
            // Use this for initialization
            void Start () {
                    evt = GameObject.Find("Cube1").GetComponent<EventDispatcher>();
            }


复制代码
获取到目标对象后,就要将本地的响应函数,添加到EventDispatcher 的事件 委托里去。
  1. /**注册侦听器函数*/
            void addEventListener(){
                    //给委托的事件类型变量赋值
                    evt.MouseDown +=OnMouseDownListener;
                    evt.MouseDrag += OnMouseDragLIstener;
            }

复制代码
evt.MouseDown 可以简单的理解成一个delegate,+= 将本地函数(delegate规定的类型和参数)赋值进去,当然了解除监听就用 -= 啦~~

完了再写出处理函数。。。
  1. /**事件响应处理函数
             * @param GameObject e 事件源的GameObject对象
             * <li> 事件响应函数的参数,参见EventDispatcher类中的相应事件Handler的参数个数
             * */
            void OnMouseDownListener(GameObject e){
                    print("on mouse down..");
                    e.transform.Rotate(20, 0, 0);
                    //移除侦听函数
                    e.GetComponent<EventDispatcher>().MouseDown -= OnMouseDownListener;
            }
            
            void OnMouseDragLIstener(GameObject e){
                    print("on mouse drag..");
            }
    复制代码
    
    
    附上EventListener源码:
    using UnityEngine;
    using System.Collections;
    /**
    * 响应事件
    * */
    public class EventListener : MonoBehaviour {
            
            private EventDispatcher evt = null;
            
            // Use this for initialization
            void Start () {
                    evt = GameObject.Find("Cube1").GetComponent<EventDispatcher>();
                    addEventListener();
            }
            /**注册侦听器函数*/
            void addEventListener(){
                    //给委托的事件类型变量赋值
                    evt.MouseDown +=OnMouseDownListener;
                    evt.MouseDrag += OnMouseDragLIstener;
            }
            
            // Update is called once per frame
            void Update () {
            
            }
            /**事件响应处理函数
             * @param GameObject e 事件源的GameObject对象
             * <li> 事件响应函数的参数,参见EventDispatcher类中的相应事件Handler的参数个数
             * */
            void OnMouseDownListener(GameObject e){
                    print("on mouse down..");
                    e.transform.Rotate(20, 0, 0);
                    //移除侦听函数
                    //e.GetComponent<EventDispatcher>().MouseDown -= OnMouseDownListener;
            }
            
            void OnMouseDragLIstener(GameObject e){
                    print("on mouse drag..");
            }
            
    }

。。代码码玩了,绑定到响应的Cube上去试试吧~~~


5.png
完成了。。。


有问题,大家一起研究,一起学习,一起进步~~
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值