144 lines
5.0 KiB
Markdown
144 lines
5.0 KiB
Markdown
# TimerModule 接入说明
|
||
|
||
基于 UnityGameFramework 的通用定时器组件插件,支持延迟执行、循环执行、按归属对象批量取消等功能。
|
||
|
||
## 导入步骤
|
||
|
||
1. 将 `Assets/Plugins/TimerModule/` 整个目录导入目标项目
|
||
2. 导入后通过 asmref 自动并入 `SepCore.Runtime` 程序集,基座项目仍可正常编译
|
||
3. 移除 TimerModule 时只需删除整个目录,不会留下残留引用
|
||
|
||
## 程序集结构
|
||
|
||
```
|
||
SepCore.Runtime.Timer.asmref → 引用 SepCore.Runtime,使 TimerComponent 与其他基座 Component 平级
|
||
```
|
||
|
||
- 依赖:`UnityGameFramework.Runtime`(框架自带)
|
||
- 无第三方依赖,纯 C# 实现
|
||
- 命名空间:`SepCore.Timer`
|
||
|
||
## 场景挂载要求
|
||
|
||
在 GameFramework 框架的组件挂载对象上(通常是场景中的 `GameEntry` 对象):
|
||
|
||
1. 添加 `TimerComponent` 组件
|
||
2. 组件会通过 `Update()` 自动驱动,无需额外初始化
|
||
3. AddComponentMenu 路径:`Game Main/Timer`
|
||
|
||
## API 使用方式
|
||
|
||
```csharp
|
||
using SepCore.Timer;
|
||
|
||
// 获取组件引用
|
||
var timer = GameEntry.GetComponent<TimerComponent>();
|
||
|
||
// 1. 一次性延迟执行
|
||
timer.ScheduleOnce(2f, () =>
|
||
{
|
||
Debug.Log("2秒后执行");
|
||
});
|
||
|
||
// 2. 无限循环(默认)
|
||
timer.ScheduleRepeat(1f, () =>
|
||
{
|
||
Debug.Log("每秒执行一次");
|
||
});
|
||
|
||
// 3. 指定次数循环(首次延迟 = 循环间隔)
|
||
timer.ScheduleRepeat(0.5f, () =>
|
||
{
|
||
Debug.Log("每0.5秒执行,共执行10次");
|
||
}, repeatCount: 10);
|
||
|
||
// 4. 自定义首次延迟 + 循环间隔
|
||
timer.ScheduleRepeat(delay: 3f, interval: 1f, () =>
|
||
{
|
||
Debug.Log("3秒后开始,然后每秒执行一次");
|
||
});
|
||
|
||
// 5. 使用 unscaledTime(不受 Time.timeScale 影响)
|
||
timer.ScheduleRepeat(1f, () =>
|
||
{
|
||
Debug.Log("暂停时也会执行");
|
||
}, timeMode: TimerTimeMode.Unscaled);
|
||
|
||
// 6. 取消单个任务
|
||
TimerHandle handle = timer.ScheduleOnce(5f, Callback);
|
||
timer.Cancel(handle); // 提前取消
|
||
|
||
// 7. 按归属对象批量取消(适合 MonoBehaviour 销毁时清理)
|
||
private void OnDestroy()
|
||
{
|
||
timer.CancelByOwner(this); // 取消所有归属于当前对象的定时器
|
||
}
|
||
|
||
// 8. 全局暂停/恢复
|
||
timer.Pause(); // 暂停所有定时器
|
||
timer.Resume(); // 恢复所有定时器
|
||
|
||
// 9. 清理所有
|
||
timer.ClearAll();
|
||
```
|
||
|
||
## TimerHandle 说明
|
||
|
||
- 值类型,可安全作为成员变量存储
|
||
- `handle.IsValid` - 检查句柄是否有效
|
||
- `TimerHandle.Invalid` - 无效句柄常量
|
||
- 实现 `IEquatable<TimerHandle>`,可用于字典键或比较
|
||
|
||
## 参数说明
|
||
|
||
| 参数 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `delay` | float | - | 首次触发前的延迟时间(秒) |
|
||
| `interval` | float | - | 循环触发间隔(秒),一次性任务忽略 |
|
||
| `repeatCount` | int | -1 | 触发次数:1=一次性,负数=无限循环,0=不创建 |
|
||
| `owner` | object | null | 任务归属对象,用于 `CancelByOwner` 批量取消 |
|
||
| `timeMode` | TimerTimeMode | Scaled | 时间源:Scaled 受 timeScale 影响,Unscaled 不受影响 |
|
||
|
||
## 最佳实践
|
||
|
||
1. **MonoBehaviour 中使用时务必设置 owner**,并在 `OnDestroy` 中调用 `CancelByOwner(this)` 避免回调执行在已销毁对象上
|
||
|
||
2. **在回调中取消自身是安全的**:回调执行时标记取消,当前帧更新结束后统一清理
|
||
|
||
3. **精度说明**:定时器基于帧更新,精度受帧率影响,适合游戏逻辑计时,不适合高精度物理模拟
|
||
|
||
4. **推荐使用便捷方法**:`ScheduleOnce` 和 `ScheduleRepeat` 比直接 `Schedule(TimerTask)` 更清晰
|
||
|
||
## 编辑器调试功能
|
||
|
||
TimerModule 内置了完整的 Editor 调试扩展,选中挂载 `TimerComponent` 的对象即可看到:
|
||
|
||
### 统计信息面板
|
||
- **活跃任务总数** - 当前正在运行的任务数量
|
||
- **Scaled/Unscaled 分布** - 受时间缩放影响的任务 vs 不受影响的任务
|
||
- **无限循环数** - `repeatCount < 0` 的永久任务数量
|
||
- **异常任务数** - 回调曾抛出异常的任务(红色高亮)
|
||
- **全局运行状态** - 绿色=运行中,橙色=已暂停
|
||
|
||
### 任务列表可视化
|
||
- **ID + 时间模式标签** - 快速识别任务,青色=Scaled,黄色=Unscaled
|
||
- **进度条** - 显示剩余时间和当前周期完成进度
|
||
- 一次性任务:显示延迟完成度
|
||
- 循环任务:显示当前周期进度
|
||
- **回调方法名** - `Class.Method` 格式,定位来源
|
||
- **归属对象** - 点击可直接 Ping 到场景中的 Owner 对象
|
||
- **异常标记** - 曾抛异常的任务会有红色背景警告
|
||
|
||
### 调试控制
|
||
- **暂停/恢复全部** - 一键控制全局定时器
|
||
- **单任务取消** - 每个任务右侧的取消按钮,可随时终止
|
||
- **清理全部** - 一键清除所有任务(含确认对话框)
|
||
|
||
## 性能特性
|
||
|
||
- 回调异常自动捕获并 LogError,不会中断其他任务或游戏
|
||
- 帧更新时遍历取消采用反向遍历,避免索引错乱
|
||
- 更新期间的删除操作延迟到帧末执行,避免并发问题
|
||
- O(n) 线性遍历,适合千级以内任务规模
|
||
- Editor 调试面板每帧自动刷新,不影响 Build 性能
|