local TaskQueue = {}; ---@class TaskQueueItem ---@field Time float 间隔时间会执行下一个 ---@field InFunc fun(InOwner:table) 进入该状态函数 ---@field TickFunc fun(InOwner:table, dt:float, st: float) 区间 Tick 函数 ---@field OutFunc fun(InOwner:table) 离开区间函数 ---@type TaskQueueItem[] TaskQueue.Config = {}; TaskQueue.Owner = nil; --- 默认不循环 TaskQueue.IsRecycle = false; ---@param Config TaskQueueItem[] function TaskQueue:new(Config, Owner) return setmetatable( { Config = Config, Owner = Owner, }, { __index = self, __metatable = self, }); end --- 启动 ---@param IsCycle bool 是否循环 function TaskQueue:Start(IsCycle) self.IsRecycle = IsCycle; self:Reset(); end TaskQueue.StartStopTime = 0; --- 停止队列 function TaskQueue:Stop() -- 暂停 self.StartStopTime = UE.GetServerTime(); GlobalTickTool:RemoveTickByOwner(self); end --- 暂停之后重新开始 function TaskQueue:Restart() --- 如果没有开启过重置,那么就无法继续执行 if self.StartStopTime == 0 then return; end local Time = UE.GetServerTime() - self.StartStopTime; self.ExecEndTime = Time + self.ExecEndTime; -- 开启 Tick GlobalTickTool:AddTick(self, self.OnTick); end --- 重置 function TaskQueue:Reset() self.CurrIndex = 1; self:OneRound(); end --- 当前正在执行的索引 TaskQueue.CurrIndex = 0; --- 从开始的执行时间 TaskQueue.ExecStartTime = 0; TaskQueue.ExecEndTime = 0; --- 一次循环 function TaskQueue:OneRound() local ConfigItem = self.Config[self.CurrIndex] GlobalTickTool:RemoveTickByOwner(self); self.ExecStartTime = UE.GetServerTime(); if ConfigItem == nil then return; end -- 开始执行第一个函数 if ConfigItem.InFunc then ConfigItem.InFunc(self.Owner); end -- 开启 Tick GlobalTickTool:AddTick(self, self.OnTick); self.ExecEndTime = self.ExecStartTime + ConfigItem.Time; end function TaskQueue:OnTick(dt, st) local Item = self.Config[self.CurrIndex]; if Item == nil then return; end if Item.TickFunc then Item.TickFunc(self.Owner, dt, st); end if st >= self.ExecEndTime then -- 直接结束 GlobalTickTool:RemoveTickByOwner(self); if Item.OutFunc then Item.OutFunc(self.Owner); end self.CurrIndex = self.CurrIndex + 1; if self.Config[self.CurrIndex] == nil then -- 这是最后一个了 self.CurrIndex = 1; -- 如果循环,那么继续开启 if self.IsRecycle then -- 下一轮回 self:OneRound(); end end end end return TaskQueue;