Unity3d通用工具类之定时触发器
時隔多日,好不容易擠出點時間來寫寫博文。不容易,請送我幾朵紅花,點個贊也行。
?
今天呢,我們主要來擴展下通用工具類==>定時觸發器。
?
顧名思義,所謂的定時觸發器,就是告訴程序在過多長時間后,我要執行某個特定的任務。
?
比如舉個小栗子:
電飯煲,相信大家都用過,當我們出去工作或者上學的時候,我們只要設置下煮飯時間,就可以安心的離開。
?
電飯煲會自動的開始計時工作,等到了你設置的時間后,他就會自動的開始煮飯啊什么的。而你卻可以在遠在千里的上班。
?
智能化,對就是這樣的效果。我們今天就來寫寫這個智能的小東西。
?
首先在設計這個小功能之前,我們要明白自己需要的是什么?如何設計?
?
1.需要什么:
(1)肯定要有個管理定時器的類,命名TimeTaskManager。(上網查了下定時器英文可以為:TimeTask,所以就取了這個名字)
(2)既然有了這個管理類,那么這個管理類要管理什么東西?對嘍,是你所要定時執行的任務。那么這個任務要包含什么東西?
1.多久時間開始執行任務肯定要,
2.重復執行間隔(有些任務要定時的重復執行,比如像機器加工廠的機器晝夜重復一個加工動作)
ok,我們命名為TimeTask
?
2.如何設計:
當我們設計一個個有相關聯的類的時候,我們可能需要紙筆來打草稿,其實完全不用,學過uml的同學可以新手拈來。這里呢我推薦使用Process On這個工具。在線繪畫工具,非常好用。
這里我們邊設計邊畫圖:
首先從TimeTask下手,對于這個類,我們要想作為一個任務,而且還是定時的。那么一下就能想到,任務執行用委托。還有程序肯定有許多任務,所以要定義一個id識別這個唯一任務。
那么定時肯定也需要一些變量,
1.private uint id;//任務id
2.private uint interval;//間隔多少秒,重復這個任務
3.private Action action;//無參委托
看到這里,這個Timetask任務類,大致建立好了。
?
哎!細心的同學可能會發現,這個Action委托是個無參委托,那么假如說我的任務方法有帶參的怎么辦呢?哎,那么問題就來了。
?
那么我再設計一個帶一個參數的Timetask<T>類,然后Action<T> action不就行了。那二個參數呢,三個參數呢......?
?
有多少個參數,你都要設計多少個類。
?
所以,對于這樣的情況,我們需要把Timetask抽象成一個基類,命名為AbstractTimeTask
?
?
哎!只要我們所有無參帶參的TimeTask都繼承與AbstractTimeTask抽象類,這樣代碼的復用性就大大提高了。
設計好了之后,我們編寫代碼:
?
?
AbstractTimeTask:
using UnityEngine; using System.Collections; using System; #region 模塊信息 /*---------------------------------------------------------------- // 模塊名:AbstractTimeT // 創建者:chen // 修改者列表: // 創建日期:2015.11.5 // 模塊描述//----------------------------------------------------------------*/ #endregion public abstract class AbstractTimeTask {#region 字段private uint m_uiTimeId;//任務idprivate int m_iInterval;//任務重復時間間隔,為0不重復private ulong m_ulNextTick;//下一次觸發的時間點#endregion#region 屬性public uint TimeId{get {return m_uiTimeId;}set {m_uiTimeId = value;}}public int Interval {get { return m_iInterval; }set { m_iInterval = value; }}public ulong NextTick {get{return m_ulNextTick;}set {this.m_ulNextTick = value;}}/// <summary>/// 抽象屬性,給子類自定義自己的action委托/// </summary>public abstract Action Action{get;set;}#endregion#region 公有方法/// <summary>/// 抽象方法,給自己自己定義執行委托/// </summary>public abstract void DoAction();#endregion }TimeTask:(這里主要先講無參)
using UnityEngine; using System.Collections; using System; #region 模塊信息 /*---------------------------------------------------------------- // 模塊名:TimeTask // 創建者:chen // 修改者列表: // 創建日期:2015.11.5 // 模塊描述:定時觸發任務類 //----------------------------------------------------------------*/ #endregion public class TimeTask : AbstractTimeTask {#region 字段private Action m_action;//定義自己的委托#endregion#region 屬性public override Action Action{get{return m_action;}set{m_action = value;}}#endregion#region 公有方法/// <summary>/// 重新父類的委托方法/// </summary>public override void DoAction(){m_action();}#endregion }
這里我們增加了NextTick字段,有什么卵用呢?主要是用來與當前程序運行時間比較,如果剛好等于這個NextTick值時,就觸發委托函數,執行任務。
細想一下,我們定時管理器類要把任務一個個加到隊列里面管理,那么肯定需要一個時間變量與task里面的時間變量進行比較。
所以,定時管理類就需要一個static uint tick變量來記錄程序運行總的時間,如果吧task加到隊列里面,task的NextTick=程序運行的總的時間tick+start(多久之后執行任務);還有就是如果task的interval的值大于0,也就是說有重復的執行,那么,就需要再加上interval的值,然后再加入到隊列里面。
分析了這么多,接著來寫管理類:
TimeTaskManager:
using UnityEngine; using System.Collections.Generic; using System.Diagnostics; using System; #region 模塊信息 /*---------------------------------------------------------------- // 模塊名:TimeTaskManager // 創建者:chen // 修改者列表: // 創建日期:2015.11.5 // 模塊描述:定時觸發器管理類 //----------------------------------------------------------------*/ #endregion public class TimeTaskManager {#region 字段private static uint m_uiNextTimeId;//總的id,需要分配給task,也就是每加如一個task,就自增private static uint m_uiTick;//總的時間,用來和task里面的nexttick變量來進行比較,看是否要觸發任務private static Queue<AbstractTimeTask> m_queue;private static Stopwatch m_stopWatch;//c#自帶的計時器,不會的自行百度private static readonly object m_queueLock = new object();//隊列鎖#endregion#region 構造方法private TimeTaskManager(){}static TimeTaskManager(){m_queue = new Queue<AbstractTimeTask>();m_stopWatch = new Stopwatch();}#endregion#region 公有方法/// <summary>/// 吧Task加入到隊列里面來管理,既然是個管理器肯定要有個添加task的操作/// </summary>/// <param name="start">多久之后開始執行ms</param>/// <param name="interval">重復時間間隔ms</param>/// <param name="action">任務委托</param>/// <returns>任務id</returns>public static uint AddTimer(uint start, int interval, Action action){AbstractTimeTask task = GetTimeTask(new TimeTask(), start, interval, action);lock (m_queueLock){m_queue.Enqueue(task);}return task.TimeId;}/// <summary>/// 周期性執行/// </summary>public static void Tick(){TimeTaskManager.m_uiTick += (uint)(m_stopWatch.ElapsedMilliseconds);//nityEngine.Debug.Log(TimeTaskManager.m_uiTick);m_stopWatch.Reset();m_stopWatch.Start();while (m_queue.Count != 0){AbstractTimeTask task;lock (m_queueLock){task = m_queue.Peek();//這里注意隊列并沒有刪除元素,只是放回元素,元素還在隊列里面}if (TimeTaskManager.m_uiTick < task.NextTick)//如果程序的總時間小于task要執行的時間點,就break點,繼續等待{break;}lock (m_queueLock){m_queue.Dequeue();}if (task.Interval > 0)//如果需要重復的話{task.NextTick += (ulong)task.Interval;lock (m_queueLock){m_queue.Enqueue(task);//再次加入隊列里面,注意哦,id不變的}task.DoAction();}else {task.DoAction();//執行委托}}}#endregion#region 私有方法private static AbstractTimeTask GetTimeTask(AbstractTimeTask task,uint start,int interval,Action action) {task.Interval = interval;task.TimeId = ++TimeTaskManager.m_uiNextTimeId;task.NextTick = TimeTaskManager.m_uiTick + start;task.Action = action;return task;}#endregion }注意:AddTimer的參數的單位是毫秒,不是秒。
接下來是實驗:
首先寫個Driver,作為驅動類。
using UnityEngine; using System.Collections; #region 模塊信息 /*---------------------------------------------------------------- // 模塊名:Driver // 創建者:chen // 修改者列表: // 創建日期:2015.11.5 // 模塊描述:驅動類 //----------------------------------------------------------------*/ #endregion public class Driver : MonoBehaviour {void Start(){TimeTaskManager.AddTimer(5000, 5000, DebugTest);InvokeRepeating("Tick", 0, 0.02f);}void Update(){}void Tick(){TimeTaskManager.Tick();}void DebugTest(){Debug.Log("111");} }創建一個空物體,然后賦予它這個腳本,作為驅動所有程序腳本。
運行,發現程序在5秒之后,每隔5秒打印一個111到控制臺。
這個定時類,非常的有用,就比如說網絡通信啊,我們可以定時的發送心跳包,還有彈出警告窗口,計時多少秒之后自動關閉等等
?
轉載于:https://www.cnblogs.com/CaomaoUnity3d/p/4940655.html
總結
以上是生活随笔為你收集整理的Unity3d通用工具类之定时触发器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript密码复杂度
- 下一篇: HDU1174(空间点到直线的距离,用叉