在游戏开发中,定时器是不可或缺的工具。Unity3D提供了多种定时器实现方法,如Update方法累积时间、协程(Coroutine)和MonoBehaviour的Invoke方法。然而,这些方法各有缺点,不够灵活和方便。因此,自行构建一个Timer定时器框架显得尤为重要。本文将详细介绍如何在Unity3D中打造Timer定时器框架,并提供相应的技术详解和代码实现。
一、为什么需要打造Timer定时器框架
Update方法累积时间:
实现原理:在组件类中定义一个时间变量,每次Update时累积时间,当时间到达特定阈值时触发函数调用。
缺点:使用起来不够方便,需要手动管理时间累积和触发逻辑。
使用协程:
实现原理:通过协程的yield return new WaitForSeconds(time)实现定时器功能。
缺点:协程虽然方便,但在管理多个定时器时可能会显得混乱,不易维护。
MonoBehaviour的Invoke方法:
实现原理:通过MonoBehaviour的Invoke接口设置定时器,在指定时间后调用某个方法。
缺点:节点隐藏后不方便触发,不便于传递参数和管理多个回调函数。
鉴于以上方法的缺点,打造一个统一的Timer定时器框架显得尤为重要。通过Timer框架,我们可以更方便地管理多个定时器,实现更复杂的定时任务。
二、Timer定时器框架的核心原理
Timer定时器框架的核心原理是:每个定时器对象是一个Timer,定时器管理系统负责管理所有的Timer对象。每次游戏Update时,定时器管理系统遍历每个Timer对象,增加其过去的时间,当过去的时间达到定时器触发时间时,触发定时器。
三、Timer定时器框架的具体实现
Timer对象定义:
每个Timer对象保存定时器的相关信息,包括回调函数、触发时间间隔、延迟时间、重复次数、已过去的时间、用户传递的参数、是否已删除和唯一标识符。
csharp
复制代码 class TimerNode{ public TimerMgr.TimerHandler callback; public float duration; // 定时器触发的时间间隔 public float delay; // 第一次触发要隔多少时间 public int repeat; // 你要触发的次数 public float passedTime; // 这个Timer过去的时间 public object param; // 用户要传的参数 public bool isRemoved; // 是否已经删除了 public int timerId; // 标识这个timer的唯一Id号}
TimerMgr定义:
TimerMgr是定时器管理系统,负责创建、管理和销毁Timer对象。它包含一个字典,用于存储TimerId到TimerNode的映射关系,以及两个缓存队列,用于新增和删除Timer时的临时存储。
csharp 复制代码 public delegate void TimerHandler(object param); public class TimerMgr{ private Dictionary<int, TimerNode> timers = new Dictionary<int, TimerNode>(); private List<TimerNode> removeTimers = new List<TimerNode>(); private List<TimerNode> newAddTimers = new List<TimerNode>(); private int autoIncId = 1; public void Init() { // 初始化操作 } public int Schedule(TimerHandler callback, float duration, int repeat, float delay, object param) { TimerNode timerNode = new TimerNode { callback = callback, duration = duration, delay = delay, repeat = repeat, passedTime = 0, param = param, isRemoved = false, timerId = autoIncId++ }; newAddTimers.Add(timerNode); return timerNode.timerId; } public void Unschedule(int timerId) { if (timers.ContainsKey(timerId)) { TimerNode timer = timers[timerId]; timer.isRemoved = true; } } public void Update() { float dt = Time.deltaTime; // 添加新Timer foreach (TimerNode timer in newAddTimers) { timers.Add(timer.timerId, timer); } newAddTimers.Clear(); // 遍历并更新Timer foreach (TimerNode timer in timers.Values) { if (timer.isRemoved) { removeTimers.Add(timer); continue; } timer.passedTime += dt; if (timer.passedTime >= (timer.delay + timer.duration)) { timer.callback(timer.param); timer.repeat--; timer.passedTime -= (timer.delay + timer.duration); timer.delay = 0; if (timer.repeat == 0) { timer.isRemoved = true; removeTimers.Add(timer); } } } // 移除已删除的Timer foreach (TimerNode timer in removeTimers) { timers.Remove(timer.timerId); } removeTimers.Clear(); }}
使用示例:
csharp 复制代码 public class Example : MonoBehaviour{ private TimerMgr timerMgr; void Start() { timerMgr = new TimerMgr(); timerMgr.Init(); // 添加一个定时器,每秒触发一次,重复5次 int timerId = timerMgr.Schedule(OnTimerTick, 1.0f, 5, 0.0f, null); } void Update() { timerMgr.Update(); } void OnTimerTick(object param) { Debug.Log("Timer ticked!"); }}
四、总结
通过打造Timer定时器框架,我们可以更方便地管理游戏中的定时器需求,实现更复杂的定时任务。Timer框架的核心原理是通过定时器管理系统在每帧更新时检查并触发已达到设定时间的Timer。具体实现包括Timer对象的定义、TimerMgr的管理以及使用示例。希望本文的介绍能帮助大家更好地理解和实现Timer定时器框架,提高游戏开发的效率和灵活性。