阶段1/UpdateScheduler调度器优化, 未嵌入

This commit is contained in:
2025-12-01 17:35:46 +08:00
parent a8adb45952
commit 07fa883537
7 changed files with 622 additions and 0 deletions

View File

@@ -15,6 +15,8 @@ namespace Demo.Game
[Content] public GameController RootGameController;
public string SourcePath;
[Content] public UpdateScheduler Scheduler = new UpdateScheduler();
protected override IEnumerator DoSomethingDuringApplyScript()
{
@@ -32,6 +34,10 @@ namespace Demo.Game
{
Keyboard.current.onTextInput -= InputCatchChar;
}
// 清理调度器
Scheduler?.Clear();
yield return base.UnloadScript();
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 88165dc714eb2714a9488d29f279ec51
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,47 @@
using UnityEngine;
namespace Demo.Game
{
/// <summary>
/// 统一Update接口用于扁平化调度
/// </summary>
public interface IUpdateable
{
/// <summary>
/// 直接Update调用无递归
/// </summary>
void DoUpdate(float currentTime, float deltaTime, ScriptableObject.TickType tickType);
/// <summary>
/// 对象名称,用于调试
/// </summary>
string GetUpdateName();
/// <summary>
/// 是否已应用脚本
/// </summary>
bool IsUpdateReady { get; }
}
/// <summary>
/// Update模式
/// </summary>
public enum UpdateMode
{
/// <summary>
/// 永久活跃(整个关卡周期)
/// </summary>
Permanent,
/// <summary>
/// 有时间范围限制
/// </summary>
TimeBound,
/// <summary>
/// 手动控制激活/停用
/// </summary>
Manual
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: af960c1cb92cc7b4492c3c573886c552

View File

@@ -0,0 +1,198 @@
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] 清空所有注册");
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4188132fc03e93e4dbb04bd7635c6152