From cccf1f75776810069c171fe6e935ddce5408c229 Mon Sep 17 00:00:00 2001
From: ninemine <1371605831@qq.com>
Date: Tue, 2 Dec 2025 09:50:22 +0800
Subject: [PATCH] =?UTF-8?q?=E9=98=B6=E6=AE=B53/=E6=B7=BB=E5=8A=A0=E6=89=8B?=
=?UTF-8?q?=E5=8A=A8=E5=90=AF=E7=94=A8=E8=B0=83=E5=BA=A6=E5=99=A8=E6=96=B9?=
=?UTF-8?q?=E6=B3=95,=20Scheduler=E4=BB=8D=E6=9C=AA=E5=90=AF=E7=94=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...1_1_performance_optimization_aggressive.md | 57 +++++-
Assets/Scripts/Framework/ScriptableObject.cs | 168 ++++++++++++------
2 files changed, 166 insertions(+), 59 deletions(-)
diff --git a/.tasks/2025-12-01_1_performance_optimization_aggressive.md b/.tasks/2025-12-01_1_performance_optimization_aggressive.md
index 3cdea91..d5300f3 100644
--- a/.tasks/2025-12-01_1_performance_optimization_aggressive.md
+++ b/.tasks/2025-12-01_1_performance_optimization_aggressive.md
@@ -293,7 +293,7 @@ using (Profiler.BeginZone("BurstJob.Schedule"))
每个Phase完成后打tag,必要时可回滚
# 当前执行步骤:
-"阶段2.5 - 阶段2整体测试"
+"阶段3.5 - 阶段3整体测试"
# 任务进度
@@ -402,12 +402,61 @@ using (Profiler.BeginZone("BurstJob.Schedule"))
- 已修改:阶段2所有代码完成,等待测试
- 更改:ScriptableObject完整实现IUpdateable接口(添加3个字段、2个虚方法、3个接口方法)
- 原因:验证接口实现无破坏性影响
+- 测试项目:
+ 1. 编译项目 - ✅ 已通过(无linter错误)
+ 2. 运行编辑器 - ✅ 用户确认成功
+ 3. 打开项目 - ✅ 用户确认成功
+ 4. 检查Inspector中新增字段是否可见 - ✅ 用户确认成功
+ 5. 验证游戏功能不受影响 - ✅ 用户确认成功
+- 阻碍因素:无
+- 状态:✅ 成功
+- Commit: 用户已提交
+
+## 阶段3:可选注册机制
+
+### 3.1 添加注册控制字段
+[2025-12-01 17:45:00]
+- 已修改:ScriptableObject.cs (添加1个字段,Line 120)
+- 更改:添加_useUpdateScheduler控制字段,默认false
+- 原因:提供可选的调度器注册开关,默认不影响现有逻辑
+- 阻碍因素:无
+- 状态:未确认
+
+### 3.2 添加脚本方法启用调度器
+[2025-12-01 17:47:15]
+- 已修改:ScriptableObject.cs (添加EnableUpdateScheduler方法,Line 178-183)
+- 更改:添加RScript可调用的启用方法
+- 原因:允许脚本中手动启用调度器
+- 阻碍因素:无
+- 状态:未确认
+
+### 3.3 修改ApplyScript添加注册逻辑
+[2025-12-01 17:49:30]
+- 已修改:ScriptableObject.cs ApplyScript方法 (添加5行,Line 678-682)
+- 更改:在ApplyScript中添加可选注册调用
+- 原因:对象应用时自动注册到调度器(如果启用)
+- 阻碍因素:无
+- 状态:未确认
+
+### 3.4 实现RegisterToScheduler方法
+[2025-12-01 17:51:45]
+- 已修改:ScriptableObject.cs (添加RegisterToScheduler私有方法,约25行,Line 684-708)
+- 更改:实现调度器注册逻辑,包含错误处理和日志
+- 原因:封装注册流程,自动获取Update模式和时间范围
+- 阻碍因素:无
+- 状态:未确认
+
+### 3.5 阶段3整体测试
+[2025-12-01 17:53:00]
+- 已修改:阶段3所有代码完成,等待测试
+- 更改:实现可选注册机制(添加1个字段、1个公开方法、1个私有方法、修改ApplyScript)
+- 原因:验证注册机制正确工作
- 测试项目:
1. 编译项目 - ✅ 已通过(无linter错误)
2. 运行编辑器 - 待测试
- 3. 打开项目 - 待测试
- 4. 检查Inspector中新增字段是否可见 - 待测试
- 5. 验证游戏功能不受影响 - 待测试
+ 3. 在测试脚本中调用EnableUpdateScheduler() - 待测试
+ 4. 检查控制台日志,确认对象被注册 - 待测试
+ 5. 验证默认行为不变(_useUpdateScheduler=false) - 待测试
- 阻碍因素:无
- 状态:未确认 → 等待用户确认:成功/不成功?
diff --git a/Assets/Scripts/Framework/ScriptableObject.cs b/Assets/Scripts/Framework/ScriptableObject.cs
index 31a31da..1b9e33d 100644
--- a/Assets/Scripts/Framework/ScriptableObject.cs
+++ b/Assets/Scripts/Framework/ScriptableObject.cs
@@ -107,16 +107,19 @@ namespace Demo
EnterGameLocalScaling = Vector3.one;
[Content, SerializeField] private bool IsSetObjectDisable = false;
[Content] public int UpdatePerFrame = 1;
-
- [Content, SerializeField, Header("UpdateMode")]
+
+ [Content, SerializeField, Header("UpdateMode")]
protected UpdateMode _updateMode = UpdateMode.Permanent;
-
- [Content, SerializeField]
+
+ [Content, SerializeField]
protected float _activeStartTime = 0f;
-
- [Content, SerializeField]
+
+ [Content, SerializeField]
protected float _activeEndTime = float.MaxValue;
+ [Content, SerializeField]
+ private bool _useUpdateScheduler = false; // 控制是否使用新的UpdateScheduler
+
///
/// 设置坐标
///
@@ -171,16 +174,25 @@ namespace Demo
{
UpdatePerFrame = Mathf.Max(1, frame);
}
-
+
+ ///
+ /// 启用新的UpdateScheduler(用于逐步迁移)
+ ///
+ [Convention.RScript.Variable.Attr.Method]
+ public void EnableUpdateScheduler()
+ {
+ _useUpdateScheduler = true;
+ }
+
///
/// 子类可重写,定义自己的Update模式
///
protected virtual UpdateMode GetUpdateMode() => UpdateMode.Permanent;
-
+
///
/// 子类可重写,定义自己的活跃时间范围
///
- protected virtual (float start, float end) GetActiveTimeRange()
+ protected virtual (float start, float end) GetActiveTimeRange()
=> (0f, float.MaxValue);
private void ScriptableObjectDoReset()
@@ -553,7 +565,7 @@ namespace Demo
if (gameObject.activeInHierarchy == false)
return;
- using (Profiler.BeginZone($"{GetType().Name}.ScriptUpdate"))
+ using (Profiler.BeginZone($"{m_GetTypeName}.ScriptUpdate"))
{
if (tickType == TickType.Reset)
{
@@ -599,8 +611,7 @@ namespace Demo
#else
MonoBehaviour,
#endif
- IHierarchyItemClickEventListener,
- IUpdateable
+ IHierarchyItemClickEventListener
{
protected virtual IEnumerator DoSomethingDuringApplyScript()
{
@@ -661,9 +672,42 @@ namespace Demo
IsEnableUpdate = false;
}
}
+
+ // 可选的调度器注册
+ if (_useUpdateScheduler && (IsSelfEnableUpdate || IsEnableUpdate))
+ {
+ RegisterToScheduler();
+ }
+
IsScriptApply = true;
}
+ ///
+ /// 注册到UpdateScheduler
+ ///
+ private void RegisterToScheduler()
+ {
+ // 获取Update模式
+ _updateMode = GetUpdateMode();
+
+ // 获取时间范围
+ if (_updateMode == UpdateMode.TimeBound)
+ {
+ (_activeStartTime, _activeEndTime) = GetActiveTimeRange();
+ }
+
+ // 注册到调度器
+ try
+ {
+ GetRoot()?.Scheduler?.Register(this, _updateMode, _activeStartTime, _activeEndTime);
+ Debug.Log($"[ScriptableObject] 已注册到调度器: {GetUpdateName()}, Mode={_updateMode}");
+ }
+ catch (System.Exception ex)
+ {
+ Debug.LogError($"[ScriptableObject] 注册到调度器失败: {ex.Message}", this);
+ }
+ }
+
public virtual IEnumerator UnloadScript()
{
if (EnsureEnableScript())
@@ -717,6 +761,63 @@ namespace Demo
}
}
+ ///
+ /// IUpdateable接口实现
+ ///
+ public partial class ScriptableObject : IUpdateable
+ {
+ ///
+ /// IUpdateable.FlatOptimizationUpdate实现 - 扁平化优化Update入口,直接更新对象自身(无递归遍历子对象)
+ ///
+ public void FlatOptimizationUpdate(float currentTime, float deltaTime, TickType tickType)
+ {
+ if (IsScriptApply == false)
+ return;
+ if (gameObject.activeInHierarchy == false)
+ return;
+
+ // 只更新自己,不递归子节点
+ if (this.IsSelfEnableUpdate && UpdatePerFrame > 0)
+ {
+ if (ScriptUpdateCounter % UpdatePerFrame == 0)
+ {
+ using (Profiler.BeginZone($"{this.ScriptName}.UpdateTicks"))
+ {
+ UpdateTicks(currentTime, deltaTime, tickType);
+ }
+ }
+ ScriptUpdateCounter += tickType == TickType.Update ? 1 : 0;
+ }
+ }
+
+ private string c_GetTypeName;
+ private string m_GetTypeName
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(c_GetTypeName))
+ {
+ c_GetTypeName = GetType().Name;
+ }
+ return c_GetTypeName;
+ }
+ }
+
+
+ ///
+ /// IUpdateable.GetUpdateName实现
+ ///
+ public string GetUpdateName()
+ {
+ return $"{ScriptName}<{m_GetTypeName}>";
+ }
+
+ ///
+ /// IUpdateable.IsUpdateReady实现
+ ///
+ public bool IsUpdateReady => IsScriptApply;
+ }
+
#endregion
public interface IAssetBundleLoader : IScriptableObject
@@ -912,47 +1013,4 @@ namespace Demo
return new(color.x, color.y, color.z);
}
}
-
- ///
- /// IUpdateable接口实现
- ///
- public partial class ScriptableObject
- {
- ///
- /// IUpdateable.FlatOptimizationUpdate实现 - 扁平化优化Update入口,直接更新对象自身(无递归遍历子对象)
- ///
- public void FlatOptimizationUpdate(float currentTime, float deltaTime, TickType tickType)
- {
- if (IsScriptApply == false)
- return;
- if (gameObject.activeInHierarchy == false)
- return;
-
- // 只更新自己,不递归子节点
- if (this.IsSelfEnableUpdate && UpdatePerFrame > 0)
- {
- if (ScriptUpdateCounter % UpdatePerFrame == 0)
- {
- using (Profiler.BeginZone($"{this.ScriptName}.UpdateTicks"))
- {
- UpdateTicks(currentTime, deltaTime, tickType);
- }
- }
- ScriptUpdateCounter += tickType == TickType.Update ? 1 : 0;
- }
- }
-
- ///
- /// IUpdateable.GetUpdateName实现
- ///
- public string GetUpdateName()
- {
- return $"{ScriptName}<{GetType().Name}>";
- }
-
- ///
- /// IUpdateable.IsUpdateReady实现
- ///
- public bool IsUpdateReady => IsScriptApply;
- }
}