工具篇:定时系统
我的解决方案
初识
为什么需要定时系统
Unity侧:
- 简化协程计时写法。
- 协程基于Monobehaviour来实现,而物体激活属性变化会导致中断调用。这可由定时器解决。
- 不需要依赖于unityAPI。
服务端侧:
简化代码 => 支持多线程、指定线程。
三种定时器
TickTimer (高频高精度的毫秒级定时)
- 支持多线程;
- 不依赖 Unity引擎环境,可在客户端服务器使用;
- 可使用外部循环驱动计时,也可使用驱动线程(内部new的)来执行;
- 定时回调默认是线程池工作线程运行,也就是在驱动线程中运行,也可外部自己驱动Handle运行;
内部使用线程安全字典ConcurrentDictionary来存储Task,遍历过程中Remove无影响。
调用线程
线程可以使用新工作线程:
1 | // 使用新线程: |
也可以在Unity的Update中调用计时器内部 UpdateTask() 方法,确定性地使用Unity主线程。
另外还有一种方式就是自己调用Handle,也可以确定性地使用外部线程(比如Unity主线程)来执行任务:
内部的新工作线程不再负责执行任务,而是对一个 线程安全队列 进行任务添加。
在外部 调用HandleTask()方法 来执行 内部队列 中的任务。
AsyncTimer (大量并发任务的定时)
- 支持多线程;
- 不依赖 Unity引擎环境,可在客户端服务器使用;
- 使用 async await异步语法计时,运行在线程池中;
- 定时回调可以在驱动线程中运行,也可在外部 Handle 运行
时间修正
1 | task.fixDelta = 0; |
由于delay的累加会出现问题(主要是因为执行代码本身需要时间),导致出现 真实运行时间 与 逻辑运行时间 有偏差,所以需要修正每次delay的值从而保证真实运行时间。
比如14:00:00起了个定时任务,delay为1小时,结果15:00:00的时候开始执行任务,任务本身花掉了10s,那么就变成14:00:10的时候去+了一小时的delay。下一次执行就变成16:00:10了而不是计划中的16:00:00。用delta修正即可。
FrameTimer (主要用于逻辑帧数的定时)
- 只可在单线程当中运行;
- 不依赖 Unity引擎环境,可在客户端服务器使用;
- 只能由外部循环驱动计数;
- 定时回调只可以在驱动线程中运行;
内部不创建线程计时,只能外部驱动。内部没有时间概念,完全不再计时只计数。
在服务端中或和客户端中,按自己的执行帧来每次调用,调用一次算一帧。其实就相当于只有前面两种Timer的Handle方法。
delay不再是时间,而是帧数。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CodingCodingK Blog!