• 关于Unity中的定时器和委托


    一、Invoke定时器

    有3种定时器,这里我们讲Invoke

    1.创建一个Canvas

    2.对Canvas进行初始化

    3.创建一个Image的UI节点作为Canvas的子节点,名字叫bg,拖进背景图片到这个节点中。

    4.创建一个game_scene的脚本挂载到Canvas下面

    5.game_scene脚本内容:

    void Start () {
            // 5秒后调用一下我们的函数,只会调用一次
            this.Invoke("onTimer", 5.0f);
            // end 
    
            // 每隔多少秒循环触发一次
            // time 多少时间以后,开始调用;
            // repeatRate每隔多少秒调用一次
            // 5秒以后开始,每隔0.5秒调用一次
             this.InvokeRepeating("onTimer", 5, 0.5f);
            // end
    
            // 定时器,是不支持参数传递的;
            this.Invoke("cancel_timer", 10f);
    }
    void cancel_timer() {
            // 取消以后,就再也不会调用这个timer了。
            this.CancelInvoke("onTimer");
    }
    
    void onTimer() {
            Debug.Log("onTimer called");
    }

    二、委托

    委托就是有一些人对A事件感兴趣,这时候出现了一个订阅中心,只要这些人订阅了这个订阅中心,一旦事件发生了,只要通知这个订阅中心,不用管有多少人对这个事件感兴趣,都由订阅中心通知给每一个订阅者,这些人就各自响应A事件。

    这个订阅中心叫做委托。好处就是不用管有多少人对某事件感兴趣,都是统一通知的。

    对于发出事件的对象,不用管有多少个人在监听自己,只要把事件丢给委托就好了,而对于监听者,不用管事件发出者是哪个对象,只要自己感兴趣的事件发生了,就去响应一些操作。

    监听者:设置一个函数,告诉委托,有事件触发了,请你调用这个设置的函数。

    委托者:事件触发了,告诉委托,委托调用监听这个事件的监听者设置的函数。

    步骤:

    1.定义委托的类型

     // 定义一个委托类型, 那么它的回掉的参数,string str, 函数;
     // 定义了监听事件的人,设置事件发生时的回掉函数的类型;
        public delegate void EventHandler(string name, int age);

    2.创建一个委托实例的引用和实例化

      // 定义一个委托引用;
      // event 修饰的委托,就只能是它的成员函数里面触发,不能在其他组件实例触发;
        public event EventHandler e;
        void Start () {
            // 定时器,是不支持参数传递的;
            this.Invoke("cancel_timer", 10.0f);
    
            this.e = new EventHandler(this.on_event_trigged);
    }

    3.监听者

       // 监听者
        void on_event_trigged(string name, int age) {
            Debug.Log("on_event_trigged" + name + age);
        }

    4.触发者

        // 触发者
        void cancel_timer() {// event修饰,强制要求委托只能是内部触发
            this.e("blake", 10);
        }

    三、委托的赋值、加法、移除、追加步骤

    1.定义委托的类型

        // 定义一个委托类型, 那么它的回掉的参数,string str, 函数;
        // 定义了监听事件的人,设置事件发生时的回掉函数的类型;
        public delegate void EventHandler(string name, int age);

    2.创建一个委托实例的引用和实例化

    // 定义一个委托引用;
        // event 修饰的委托,就只能是它的成员函数里面触发;
        public event EventHandler e;       
    
        void Start () {
            // 定时器,是不支持参数传递的;
            this.Invoke("cancel_timer", 5.5f);
    
            this.e = new EventHandler(this.on_event_trigged);
    
            EventHandler e1 = new EventHandler(this.on_event_trigged1);
            EventHandler e2 = new EventHandler(this.on_event_trigged2);
         
      
         //会覆盖之前的只有一个监听者的时候,会响应on_event_trigged1和on_event_trigged2
         //this.e = e1 + e2;
    
         //追加,会响应on_event_trigged1和on_event_trigged2和on_event_trigged
           this.e += (e1 + e2);
    
            //Debug.Log("game scene start!!!");
            // 隐士的创建了一个委托对象
            //this.e += this.on_event_trigged;
            //this.e += this.on_event_trigged1;
            //this.e += this.on_event_trigged2;
    
         //移除
            //this.e -= this.on_event_trigged2;
    } 

    3.监听者

        // 监听者1
        void on_event_trigged1(string name, int age)
        {
            Debug.Log("on_event_trigged1" + name + age);
        }
    
        // 监听者2
        void on_event_trigged2(string name, int age)
        {
            Debug.Log("on_event_trigged2" + name + age);
        }
    
        // 监听者3
        void on_event_trigged(string name, int age) {
            Debug.Log("on_event_trigged" + name + age);
        }

     

    4.触发者

        // 触发者
        void cancel_timer() {// event修饰,强制要求委托只能是内部触发
            this.e("blake", 10);
        }

    四、委托在父节点中,监听者和响应函数在子节点中

    1.game_scene脚本中定义委托的类型

        // 定义一个委托类型, 那么它的回掉的参数,string str, 函数;
        // 定义了监听事件的人,设置事件发生时的回掉函数的类型;
        public delegate void EventHandler(string name, int age);

    2.game_scene脚本中创建一个委托实例的引用

        // 定义一个委托引用;
        // event 修饰的委托,就只能是它的成员函数里面触发;
        public event EventHandler e;       

    3.Canvas的子节点item下挂载一个叫做item的脚本,item脚本里面的监听者:

    public class item : MonoBehaviour {
            game_scene scene;
        // Use this for initialization
    
        void Start () {
            Debug.Log("item start");
        // 监听game_scene里面的事件;
            this.scene = this.transform.parent.GetComponent<game_scene>();
            this.scene.e += this.on_item_event_called;
    
        }
    
             void on_item_event_called(string name, int age) {
                Debug.Log("on_item_event_called: " + name + " " + age);
            }
        }

    4.触发者方法1,在父节点canvas的game_scene组件脚本里面的触发者触发委托

       void Start () {
            // 定时器,是不支持参数传递的;
            this.Invoke("cancel_timer", 5.5f);
       }
    
       // 触发者
        void cancel_timer() {// event修饰,强制要求委托只能是内部触发
            this.e("blake", 10);
        }

     5.触发者方法2,在子节点item的item组件脚本里面的触发者触发委托

    game_scene:

        // 定义一个委托引用;
        // 这里不能用event修饰,因为是在别的节点的组件实例里触发
        public  EventHandler e;  

    item:

    void Start () {
                Debug.Log("item start");
            // 监听game_scene里面的事件;
                this.scene =     this.transform.parent.GetComponent<game_scene>();
                this.scene.e += this.on_item_event_called;
         
                //触发语句
                this.Invoke("on_trigger", 5);
        }
    
            void on_trigger() {
                // 如果是event修饰的委托,只能内部触发。
                this.scene.e("haha", 20);
            }                 

     注意:

    1.可以把委托赋值为空

    this.e=null;

    2.一般把监听者注册到委托对象中是用

     this.e+=this.on_event_trigged;

     

    3.Unity有帮我们分装了一种委托类型的写法,叫系统封装的委托类

    (1)方法1的定义

         public delegate void EventHandler(string name, int age);

    (2)方法2的定义---封装好的,F12进去其实就是方法1

      public event Action<int> action = null;
      public event Action<int, string, int, int> action2;

    方法2的添加

        void Start () {
            // 定时器,是不支持参数传递的;
            this.Invoke("cancel_timer", 5.5f);
    
        this.action += this.on_action_called;
    }

    方法2的响应

     void on_action_called(int num) {
            Debug.Log("num = " + num);
    }

    方法2的触发

        // 触发者
        void cancel_timer() {
            if (this.action != null) {
                this.action(5000);
            }
        }
  • 相关阅读:
    服务器端口
    Format(const wchar_t *,...)”: 不能将参数 1 从“const char [3]”转换为“const wchar_t *”.
    图片格式
    CreateEx
    电力谐波
    [OGeek2019]babyrop
    Simple Inject
    [GXYCTF2019]BabySQli
    [CISCN2019 华北赛区 Day2 Web1]Hack World
    极客大挑战2019
  • 原文地址:https://www.cnblogs.com/HangZhe/p/6916881.html
Copyright © 2020-2023  润新知