前言
用于时间管理、定时执行函数、间隔执行函数
核心代码
- TimeTween.cs
using System;
public enum TweenType
{
ToDelay,
IntervalCall,
}
public class TimeTween
{
public int tweenId
{
get
{
return id;
}
set
{
id=value;
}
}
private int id;
private float duringTime;
private Action callback;
private float runTime;
private float spanTime;
private float spanTimer;
private TweenType? tweenType;
public TimeTween()
{
Init();
}
public void Init()
{
id=-1;
duringTime=0.0f;
runTime=0.0f;
spanTimer=0.0f;
spanTime=0.0f;
callback=null;
tweenType=null;
}
public void ToDelay(int id,float time,Action callback)
{
this.id=id;
tweenType=TweenType.ToDelay;
duringTime=time;
this.callback=callback;
runTime=0.0f;
}
public void IntervalCall(int id,float spanTime,Action callback,float duringTime)
{
this.id=id;
tweenType=TweenType.IntervalCall;
this.duringTime=duringTime;
this.callback=callback;
runTime=0;
spanTimer=spanTime;
this.spanTime=spanTime;
}
public bool CheckEnd()
{
return runTime>=duringTime;
}
public void SetCallback(Action action)
{
callback=action;
}
public void Finish(bool isFinish=false,int needCallback=0)
{
if(needCallback==0)
{
if(tweenType.Value==TweenType.ToDelay && callback!=null)
{
callback();
}
}
else if(needCallback==1)
{
callback?.Invoke();
}
}
public bool TweenTo(float deltaTime)
{
bool needKill=false;
runTime+=deltaTime;
switch(tweenType.Value)
{
case TweenType.ToDelay:
break;
case TweenType.IntervalCall:
spanTimer+=deltaTime;
if(spanTimer>=spanTime)
{
spanTimer-=spanTime;
try
{
callback?.Invoke();
}
catch(Exception e)
{
needKill=true;
}
}
break;
}
if(CheckEnd())
{
needKill=true;
if(callback!=null &&tweenType.Value!=TweenType.IntervalCall)
{
callback();
}
}
return needKill;
}
}
- TimerUtils.cs
using System.Collections.Generic;
using System;
public static class TimerUtils
{
private static Dictionary<int,TimeTween> tweenList=new Dictionary<int,TimeTween>();
private static List<TimeTween> cacheList=new List<TimeTween>();
private const int maxNum=1024;
private static int count=0;
private const int cacheMaxNum=32;
private static int idCounter=0;
private static void Add(TimeTween tween)
{
if(!tweenList.ContainsKey(tween.tweenId))
{
tweenList.Add(tween.tweenId,tween);
count++;
}
}
private static void Remove(TimeTween tween)
{
if(tweenList.ContainsKey(tween.tweenId))
{
AddToCache(tween);
tweenList.Remove(tween.tweenId);
count--;
}
}
private static bool IsPlaying(TimeTween tween)
{
if(tweenList.ContainsKey(tween.tweenId))
return true;
else
return false;
}
private static void AddToCache(TimeTween tween)
{
if(cacheList.Count<cacheMaxNum)
{
cacheList.Add(tween);
}
}
private static TimeTween GetFromCache()
{
TimeTween tween=null;
if(cacheList.Count>0)
{
tween=cacheList[0];
cacheList.Remove(tween);
}
return tween;
}
private static TimeTween GetNewTween()
{
TimeTween curTween=null;
curTween=GetFromCache();
if(curTween!=null)
{
int tweenId=curTween.tweenId;
curTween.Init();
curTween.tweenId=tweenId;
}
else
{
curTween=new TimeTween();
idCounter++;
curTween.tweenId=idCounter;
}
return curTween;
}
public static TimeTween ToDelay(float duringTime,Action callback)
{
TimeTween curTween=null;
if(duringTime>0)
{
if(count<maxNum)
{
curTween=GetNewTween();
curTween.ToDelay(curTween.tweenId,duringTime,callback);
Add(curTween);
}
}
return curTween;
}
public static TimeTween IntervalCall(float spanTime,Action callback,float duringTime)
{
TimeTween curTween=null;
if(duringTime>0&&spanTime>0)
{
if(count<maxNum)
{
curTween=GetNewTween();
curTween.IntervalCall(curTween.tweenId,duringTime,callback);
Add(curTween);
}
}
return curTween;
}
public static void Kill(TimeTween tween,bool isFinish=false)
{
if(tween!=null)
{
if(IsPlaying(tween))
{
Remove(tween);
if(isFinish)
{
tween.Finish(true,0);
}
}
}
}
public static void KillWithCallback(TimeTween tween,bool isFinish=false,bool needCallback=false)
{
if(tween!=null)
{
if(IsPlaying(tween))
{
Remove(tween);
if(isFinish)
{
if(needCallback)
{
tween.Finish(true,1);
}
else
{
tween.Finish(true,-1);
}
}
else
{
if(needCallback)
{
tween.Finish(false,1);
}
}
}
}
}
public static bool CheckEnd(TimeTween tween)
{
return tween!=null && tween.CheckEnd();
}
public static void ChanageCallback(TimeTween tween,Action action)
{
tween?.SetCallback(action);
}
public static void Update(float deltaTime)
{
if(count>0)
{
int[] keyArr=new int[tweenList.Count];
tweenList.Keys.CopyTo(keyArr,0);
for(int i=0;i<keyArr.Length;i++)
{
bool needKill=tweenList[keyArr[i]].TweenTo(deltaTime);
if(needKill)
{
Remove(tweenList[keyArr[i]]);
}
}
}
}
}
说明:只需要将TimerUtils 中的Update放入Unity主Update进行驱动,
然后调用相应的ToDelay和IntervalCall函数即可。
- ToDelay:延迟duringTime秒执行callback
- IntervalCall:间隔spanTime秒执行一次callback,总共持续多久duringTime秒
- InTimeCall:具体时间进行执行
扩展:以上工具方法还能扩展到对值的缓动进行补间运算。实现类似于DOTween的之变换效果。