Unity3D延迟回调的封装
2016-12-28 14:03
459 查看
最近,整理项目框架逻辑时,无意中翻到n年前封装的延迟回调管理器,就拎出来说道说道:
先说一下系统提供的几种常用的延迟回调方式:
1)Invoke(Invoke、CancelInvoke):首先需要继承自MonoBehaviour,其次使用的是函数名作为参数调用,比较麻烦,容易出错(运行时才会审查,编译检查不到);
2)Coroutine(StartCoroutine、StopCoroutine):仍然继承自MonoBehaviour,调用时可以使用函数名,也可以直接传入委托,效率上不高,每次调用都会牵扯到额外的堆内存分配,并且所挂载的游戏对象状态不能被打断,否则执行也会被打断;
3、Update:依赖MonoBehaviour,每次调用需要单独申请变量,重写逻辑,也会因状态打断而停止执行;
在不使用插件的情况下,索性进行一些封装,综合各自的优点,去其糟粕:
封装之后仅需要在主函数逻辑中进行驱动计时,之后就可以根据需要方便的延迟及取消延迟了。(PS:因为只是简单的封装,因此还有以下缺点:1)递归回调的问题;2)无法取消匿名的回调函数。)
当然,也有一些比较方便使用的插件,这个可以根据需要自行研究了,eg:Vision Timer等,DoTween等也有提供接口功能。
先说一下系统提供的几种常用的延迟回调方式:
1)Invoke(Invoke、CancelInvoke):首先需要继承自MonoBehaviour,其次使用的是函数名作为参数调用,比较麻烦,容易出错(运行时才会审查,编译检查不到);
2)Coroutine(StartCoroutine、StopCoroutine):仍然继承自MonoBehaviour,调用时可以使用函数名,也可以直接传入委托,效率上不高,每次调用都会牵扯到额外的堆内存分配,并且所挂载的游戏对象状态不能被打断,否则执行也会被打断;
3、Update:依赖MonoBehaviour,每次调用需要单独申请变量,重写逻辑,也会因状态打断而停止执行;
在不使用插件的情况下,索性进行一些封装,综合各自的优点,去其糟粕:
public class InvokeManager { private InvokeManager() //泛型单件 { timeDelayLst = new List<float>(); timeStateLst = new List<bool>(); callbackDelayLst = new List<System.Action>(); } private IList<float> timeDelayLst; private IList<bool> timeStateLst; private IList<System.Action> callbackDelayLst; public void Invoke(float _timeDelay, System.Action _callback) { timeDelayLst.Add(_timeDelay); timeStateLst.Add(false); callbackDelayLst.Add(_callback); } public int CancelInvoke(System.Action _callback, bool _cancelAll = false) //false:仅取消最后注册的(和延迟时间无关);返回int型,可以根据剩余的次数立即执行未执行的回调函数 { int tCount = 0; for(int i = callbackDelayLst.Count - 1; i >= 0; i--) { if(callbackDelayLst[i].Equals(_callback)) { tCount++; timeDelayLst.RemoveAt(i); timeStateLst.RemoveAt(i); callbackDelayLst.RemoveAt(i); if(!_cancelAll) { return tCount; } } } return tCount; } public void ClearInvoke() { timeDelayLst.Clear(); timeStateLst.Clear(); callbackDelayLst.Clear(); } public void TickUpdate(float _deltaTime) { filtTick(_deltaTime); for(int i = timeStateLst.Count - 1; i >= 0; i--) { timeStateLst[i] = false; } } private void filtTick(float _deltaTime) { for(int i = timeDelayLst.Count - 1; i >= 0; i--) { if(timeStateLst.Count > i && !timeStateLst[i]) { timeDelayLst[i] -= _deltaTime; timeStateLst[i] = true; if(timeDelayLst[i] <= 0) { var tCallback = callbackDelayLst[i];//从后向前遍历:删除最后注册(和延迟时间无关)的事件回调(可以自行扩展根据延迟时间进行删除) timeDelayLst.RemoveAt(i); timeStateLst.RemoveAt(i); callbackDelayLst.RemoveAt(i); tCallback(); filtTick(_deltaTime); } } } } }
封装之后仅需要在主函数逻辑中进行驱动计时,之后就可以根据需要方便的延迟及取消延迟了。(PS:因为只是简单的封装,因此还有以下缺点:1)递归回调的问题;2)无法取消匿名的回调函数。)
当然,也有一些比较方便使用的插件,这个可以根据需要自行研究了,eg:Vision Timer等,DoTween等也有提供接口功能。
相关文章推荐
- android使用gson和泛型解析服务器回调的封装
- IOS自己封装的异步下载(get)Block方式回调给大家分享下
- Unity3D调用自己封装的dll
- Unity3D 封装自己的Debug类库dll
- Unity3D 与 objective-c 之间数据交互。iOS SDK接口封装Unity3D接口
- 【Unity3D 5.6版本使用(2)】Unity5中WebGL平台封装的一些技巧 (转载)
- dubbo学习七--参数回调,本地存根,延迟暴露,并发控制
- Unity3d中调用C/C++封装的DLL
- [Unity3d]调用自己封装的dll
- 第一百五十六节,封装库--JavaScript,延迟加载
- Retrofit--合理封装回调能让你的项目高逼格
- Swift 简单封装UISwipeGestureRecognizer + 闭包回调监听事件,便于不同场景的 UIView调用
- Unity3D在IOS、Android上使用C++并回调的究极解决方案
- Unity3d通过Action注册事件,回调方法
- 超级简单RecycleViewAdapter的封装-支持多视图,多点击回调
- select_resultMap_关联查询_association定义关联对象封装规则,关联查询_分步查询&延迟加载
- 用回调封装OKHttp
- Unity3D 事件回调
- Unity3D之AssetBundle资源加载封装
- 【Unity3D自学记录】 Unity 延迟执行一段代码的较为优雅的方式