Files
Convention-Unity-Demo/Assets/Scripts/Framework/UpdateScheduler/UpdateScheduler.cs

199 lines
6.8 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using Convention;
using UnityEngine;
namespace Demo.Game
{
/// <summary>
/// 全局扁平化Update调度器
/// </summary>
public class UpdateScheduler
{
// 永久活跃对象
private readonly List<IUpdateable> permanentObjects = new();
// 时间范围对象(排序队列)
private readonly SortedDictionary<float, List<IUpdateable>> activationQueue = new();
private readonly SortedDictionary<float, List<IUpdateable>> deactivationQueue = new();
// 当前活跃对象
private readonly List<IUpdateable> activeObjects = new();
// 统计信息
public int TotalRegistered => permanentObjects.Count + activationQueue.Values.Sum(l => l.Count);
public int CurrentActive => permanentObjects.Count + activeObjects.Count;
/// <summary>
/// 注册对象到调度器
/// </summary>
public void Register(IUpdateable obj, UpdateMode mode, float startTime = 0f, float endTime = float.MaxValue)
{
if (obj == null)
{
Debug.LogError("[UpdateScheduler] 尝试注册null对象");
return;
}
switch (mode)
{
case UpdateMode.Permanent:
if (!permanentObjects.Contains(obj))
{
permanentObjects.Add(obj);
Debug.Log($"[UpdateScheduler] 注册永久对象: {obj.GetUpdateName()}");
}
break;
case UpdateMode.TimeBound:
// 注册激活时间
if (!activationQueue.ContainsKey(startTime))
activationQueue[startTime] = new List<IUpdateable>();
if (!activationQueue[startTime].Contains(obj))
{
activationQueue[startTime].Add(obj);
Debug.Log($"[UpdateScheduler] 注册时间范围对象: {obj.GetUpdateName()} ({startTime:F2}s - {endTime:F2}s)");
}
// 注册停用时间
if (!deactivationQueue.ContainsKey(endTime))
deactivationQueue[endTime] = new List<IUpdateable>();
if (!deactivationQueue[endTime].Contains(obj))
{
deactivationQueue[endTime].Add(obj);
}
break;
case UpdateMode.Manual:
// 手动模式不自动注册
Debug.Log($"[UpdateScheduler] 手动模式对象: {obj.GetUpdateName()}");
break;
}
}
/// <summary>
/// 手动激活对象Manual模式
/// </summary>
public void Activate(IUpdateable obj)
{
if (!activeObjects.Contains(obj))
{
activeObjects.Add(obj);
}
}
/// <summary>
/// 手动停用对象Manual模式
/// </summary>
public void Deactivate(IUpdateable obj)
{
activeObjects.Remove(obj);
}
/// <summary>
/// 主Update循环 - 扁平化遍历
/// </summary>
public void DoUpdate(float currentTime, float deltaTime, ScriptableObject.TickType tickType)
{
// 时间分片管理
using (Profiler.BeginZone("UpdateScheduler.TimeSlicing"))
{
ProcessActivations(currentTime);
ProcessDeactivations(currentTime);
}
// 扁平更新所有活跃对象
using (Profiler.BeginZone($"UpdateScheduler.FlatUpdate (Permanent:{permanentObjects.Count} Active:{activeObjects.Count})"))
{
// 永久活跃对象
for (int i = 0; i < permanentObjects.Count; i++)
{
if (permanentObjects[i]?.IsUpdateReady == true)
{
permanentObjects[i].DoUpdate(currentTime, deltaTime, tickType);
}
}
// 当前活跃对象
for (int i = activeObjects.Count - 1; i >= 0; i--)
{
if (activeObjects[i] == null || !activeObjects[i].IsUpdateReady)
{
activeObjects.RemoveAt(i);
continue;
}
activeObjects[i].DoUpdate(currentTime, deltaTime, tickType);
}
}
}
private void ProcessActivations(float currentTime)
{
while (activationQueue.Count > 0)
{
var firstKey = activationQueue.Keys.First();
if (firstKey > currentTime) break;
var objects = activationQueue[firstKey];
foreach (var obj in objects)
{
if (obj != null && !activeObjects.Contains(obj))
{
activeObjects.Add(obj);
Debug.Log($"[UpdateScheduler] 激活: {obj.GetUpdateName()} @ {currentTime:F2}s");
}
}
activationQueue.Remove(firstKey);
}
}
private void ProcessDeactivations(float currentTime)
{
while (deactivationQueue.Count > 0)
{
var firstKey = deactivationQueue.Keys.First();
if (firstKey > currentTime) break;
var objects = deactivationQueue[firstKey];
foreach (var obj in objects)
{
activeObjects.Remove(obj);
if (obj != null)
{
Debug.Log($"[UpdateScheduler] 停用: {obj.GetUpdateName()} @ {currentTime:F2}s");
}
}
deactivationQueue.Remove(firstKey);
}
}
/// <summary>
/// 重置调度器用于Reset/Restart
/// </summary>
public void Reset()
{
activeObjects.Clear();
Debug.Log("[UpdateScheduler] 重置完成");
}
/// <summary>
/// 清空所有注册
/// </summary>
public void Clear()
{
permanentObjects.Clear();
activationQueue.Clear();
deactivationQueue.Clear();
activeObjects.Clear();
Debug.Log("[UpdateScheduler] 清空所有注册");
}
}
}