本文只作为参考,个人水平有限,望见谅!
在写代码的时候经常碰到过一定时间之后执行某个方法的情况,刚开始时会定义一个bool值和一些时间count进行时间上的判断,于是乎就出现了许多的变量,时间一长,自己都不知道哪个变量对应着哪些代码。熟悉Unity一段时间之后发现了StartCoroutine()也就是所谓的协程函数,就开始大肆使用协程,关于协程和线程的区别在这就不说啦。但是用了一段时间发现协程虽然可以应对诸如过一段时间执行某段函数的情况,但是如果说要在这段时间内执行另一个函数的话,要么就是放到Update()中去判断,要么就是用两个协程,一个判断时间,一个循环执行函数。所以干脆就写了一个Timer类将所有情况都包括进去,这就是为什么会写这个类的原因。
这边给出了Timer类的两种实现方法,一种就是通过判读时间是否超过预定时间来实现的,好处就在于可以得到执行时间;另一种就是用刚刚说的两个协程的方式来实现,好处在于使用的是迭代器,在做复杂的时间判断时Unity不会报错。两种代码都没有考虑到List存储的性能消耗,大家如果不嫌弃的话就拿去用吧。
Timer.cs(实现一)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public delegate void TimerStart();
public delegate void TimerEnd();
public class Timer
{
float duringTime;
float oldTime = -1;
bool flag;
TimerStart OnStart;
TimerEnd OnEnd;
static List<Timer> timerList = new List<Timer>();
public Timer(float time, TimerStart startFunc, TimerEnd endFunc, bool alwaysDO)
{
duringTime = time;
OnStart = startFunc;
OnEnd = endFunc;
oldTime = Time.time;
flag = alwaysDO;
OnStart();
timerList.Add(this);
}
public static void Update()
{
foreach (var timer in timerList)
timer.update();
}
public float getOldTime() { return oldTime; }
public void stopTimer() { oldTime = -1; }
public static void stopAllTimer()
{
foreach (var time in timerList)
time.stopTimer();
}
void update()
{
if (oldTime != -1)
{
if (!flag)
Function();
else
{
OnStart();
Function();
}
}
}
void Function()
{
if (Time.time > oldTime + duringTime)
{
oldTime = -1;
OnEnd();
}
}
}
Test.cs (需要Update的调用)
using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
void Start()
{
Timer timer1 = new Timer(3, () => { Debug.Log("alwaysDo"); }, () => {Debug.Log("stopTimer1"); }, true);
Timer timer2 = new Timer(5, () => { Debug.Log("noAlways"); }, () => { Debug.Log("stopTimer2"); }, false);
}
void Update() { Timer.Update(); }
}
Timer.cs(实现二)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public delegate void TimerStart(int index,bool isDone);
public delegate void TimerEnd(int index);
public class Timer : MonoBehaviour
{
private static Timer instance;
private static ArrayList stopList;
public static void Init()
{
GameObject go = new GameObject("Timer");
instance = go.AddComponent<Timer>();
stopList = new ArrayList();
}
public static Timer GetInstance() { return instance; }
public void StartTimer(TimerStart startFunction,TimerEnd endFunction,float time,bool alwaysDo)
{
StartCoroutine(RunTimer(startFunction, endFunction, time, alwaysDo));
}
public void StopTimer(int index) { stopList[index]=true;}
IEnumerator RunTimer(TimerStart startFunction,TimerEnd endFunction,float time,bool alwaysDo)
{
int index = stopList.Add(false);
StartCoroutine(StopTimer(endFunction,time,index));
bool isDone = false;
while (true)
{
if (alwaysDo)
startFunction(index, (bool)stopList[index]);
else if(!isDone)
{
startFunction(index, (bool)stopList[index]);
isDone = true;
}
if ((bool)stopList[index]) { break; }
yield return null;
}
}
IEnumerator StopTimer(TimerEnd endFunction,float time,int index)
{
yield return new WaitForSeconds(time);
if(!(bool)stopList[index])
{
endFunction(index);
stopList[index] = true;
}
}
}
Test.cs (需要Init的调用)
using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
void Awake() { Timer.Init(); }
void Start()
{
Timer.GetInstance().StartTimer((int i, bool done) =>
{
Debug.Log(i);
Debug.Log(done);
}, (int i) => { Debug.Log(i); }, 2, true);
}
}