Skip to content

定时器组件

简介

说明

定时器组件是 ET 框架中一个重要的功能组件,它提供了一套完整的定时任务管理方案。主要功能包括:

  • 延时执行任务
  • 循环定时任务
  • 定时器的取消和销毁

核心特性

  • 多种定时器类型: 支持一次性定时器、重复性定时器和异步等待定时器
  • 异步支持: 提供异步等待接口,支持现代异步编程模式
  • 性能优化: 使用高效的数据结构,优化定时器查找和管理

定时器类型

1. 一次性定时器 (OnceTimer)

用于执行一次性的延时任务:

csharp
// 创建一个3秒后执行的定时器
long timerId = timerComponent.NewOnceTimer(TimeInfo.Instance.ClientNow() + 3000, type, args);

2. 重复性定时器 (RepeatedTimer)

用于执行周期性重复的任务:

csharp
// 创建一个每1秒执行一次的定时器
long timerId = timerComponent.NewRepeatedTimer(1000, type, args);

3. 异步等待定时器 (OnceWaitTimer)

用于异步等待特定时间:

csharp
// 异步等待2秒
await timerComponent.WaitAsync(2000);

// 等待到指定时间
await timerComponent.WaitTillAsync(tillTime);

4. 帧定时器

用于每帧执行的任务:

csharp
// 创建一个每帧执行的定时器
long timerId = timerComponent.NewFrameTimer(type, args);

使用建议

  1. 短时间等待场景:

    • 推荐使用 WaitTillAsync
    • 适用于需要逻辑连贯的短时间等待
    • 例如:短暂的动画等待、简单的延时效果
  2. 长时间等待场景:

    • 推荐使用 NewOnceTimer
    • 适用于需要热更新的长时间等待
    • 例如:长时间的游戏状态检查、定期的数据同步
  3. 循环任务场景:

    • 推荐使用 NewRepeatedTimer
    • 适用于需要定期执行的任务
    • 例如:背包刷新、buff更新等

定时器管理

取消定时器

csharp
// 通过定时器ID取消
timerComponent.Remove(ref timerId);

安全性考虑

  1. 时间检查
  • 重复性定时器的最小间隔为100ms
  • 小于100ms的时间间隔会触发错误提示
  1. 取消机制
  • 提供 Remove 方法安全地移除定时器

基础用法

接下来将通过MoveComponent组件来对定时器进行一个简单的使用示例

MoveComponent.cs
csharp
public class MoveComponent : Entity, IAwake, IDestroy
{
}
MoveComponentSystem.cs
csharp
using System;
using UnityEngine;

namespace MH
{
    [EntitySystem]
    public class MoveComponentAwakeSystem : AwakeSystem<MoveComponent>
    {
        protected override void Awake(MoveComponent self)
        {
        }
    }

    [EntitySystem]
    public class MoveComponentDestroySystem : DestroySystem<MoveComponent>
    {
        protected override void Destroy(MoveComponent self)
        {
        }
    }
    public static class MoveComponentSystem
    {
        
    }
}

现在来定义一下需求:

  1. 每 1 秒输出一次位置信息
  2. 5秒后停止第1个定时器

之后来到TimerInvokeType.cs文件添加一下定时器的类型

csharp
namespace MH
{
    public static class TimerInvokeType
    {
        //test
        public const int TestTimer = 1;
        public const int CoroutineTimeout = 1001;



        //New TimeInvokeType
        public const int MoveComponent_TimeInvokeType1 = 1002;
        public const int MoveComponent_TimeInvokeType2 = 1003;
    }
}

定义完定时器类型后修改MoveComponent.cs以及MoveComponentSystem.cs

csharp
using System;
namespace MH
{
    public class MoveComponent : Entity, IAwake, IDestroy
    {
        public float X;
        public float Y;
        public float Z;

        public long TimerId1;
        public long TimerId2;
    }
}
csharp
using System;
using UnityEngine;

namespace MH
{
    [Invoke(TimerInvokeType.MoveComponent_TimeInvokeType1)]
    public class MoveComponent_Timer1 : ATimer<MoveComponent>
    {
        protected override void Run(MoveComponent self)
        {
            Debug.Log($"Current: X:{self.X} Y:{self.Y} Z:{self.Z}");
        }
    }
    [Invoke(TimerInvokeType.MoveComponent_TimeInvokeType2)]
    public class MoveComponent_Timer2 : ATimer<MoveComponent>
    {
        protected override void Run(MoveComponent self)
        {
            self.Root.GetComponent<TimerComponent>().Remove(ref self.TimerId1);
            Debug.Log("停止定时器1");
        }
    }
    [EntitySystem]
    public class MoveComponentAwakeSystem : AwakeSystem<MoveComponent>
    {
        protected override void Awake(MoveComponent self)
        {
            self.TimerId1 = self.Root.GetComponent<TimerComponent>().NewRepeatedTimer(
                1000,
                TimerInvokeType.MoveComponent_TimeInvokeType1,
                self
            );
            self.TimerId2 = self.Root.GetComponent<TimerComponent>().NewOnceTimer(
                TimeInfo.Instance.ClientNow() + 5000,
                TimerInvokeType.MoveComponent_TimeInvokeType2,
                self
            );
        }
    }

    [EntitySystem]
    public class MoveComponentDestroySystem : DestroySystem<MoveComponent>
    {
        protected override void Destroy(MoveComponent self)
        {
            var timerComponent = self.Root.GetComponent<TimerComponent>();
            timerComponent.Remove(ref self.TimerId1);
            timerComponent.Remove(ref self.TimerId2);
        }
    }
    public static class MoveComponentSystem
    {
    }
}

这时候来到MainInit_EventView脚本中为Root添加MoveComponent组件

csharp
namespace MH
{
    [Event(SceneType.Main)]
    public class MainInit_EventView : AEvent<Scene, Main_Init>
    {
        protected override async ETTask Run(Scene scene, Main_Init a)
        {
            //...
            scene.AddComponent<MoveComponent>();
        }
    }
}

效果演示

效果视频

以下视频展示了定时器组件效果演示

技术支持

获取帮助

  • 💬 加入QQ群讨论交流(ET框架群) : 474643097
  • ⭐ 在GitHub上关注项目获取最新更新

Released under the MIT License.