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

199 lines
6.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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].FlatOptimizationUpdate(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].FlatOptimizationUpdate(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] 清空所有注册");
}
}
}