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; - } }