关于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);
        }
    }
原文地址:https://www.cnblogs.com/HangZhe/p/6916881.html