2025-12-01 17:35:46 +08:00
|
|
|
|
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)
|
|
|
|
|
|
{
|
2025-12-01 17:54:03 +08:00
|
|
|
|
permanentObjects[i].FlatOptimizationUpdate(currentTime, deltaTime, tickType);
|
2025-12-01 17:35:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 当前活跃对象
|
|
|
|
|
|
for (int i = activeObjects.Count - 1; i >= 0; i--)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (activeObjects[i] == null || !activeObjects[i].IsUpdateReady)
|
|
|
|
|
|
{
|
|
|
|
|
|
activeObjects.RemoveAt(i);
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-01 17:54:03 +08:00
|
|
|
|
activeObjects[i].FlatOptimizationUpdate(currentTime, deltaTime, tickType);
|
2025-12-01 17:35:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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] 清空所有注册");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|