199 lines
6.9 KiB
C#
199 lines
6.9 KiB
C#
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] 清空所有注册");
|
||
}
|
||
}
|
||
}
|
||
|