阶段1/UpdateScheduler调度器优化, 未嵌入
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
8
Assets/Scripts/Framework/UpdateScheduler.meta
Normal file
8
Assets/Scripts/Framework/UpdateScheduler.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88165dc714eb2714a9488d29f279ec51
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
47
Assets/Scripts/Framework/UpdateScheduler/IUpdateable.cs
Normal file
47
Assets/Scripts/Framework/UpdateScheduler/IUpdateable.cs
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af960c1cb92cc7b4492c3c573886c552
|
||||
198
Assets/Scripts/Framework/UpdateScheduler/UpdateScheduler.cs
Normal file
198
Assets/Scripts/Framework/UpdateScheduler/UpdateScheduler.cs
Normal 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] 清空所有注册");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4188132fc03e93e4dbb04bd7635c6152
|
||||
Reference in New Issue
Block a user