Co-authored-by: m0_75251201 <m0_75251201@noreply.gitcode.com> Reviewed-on: Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite#55
264 lines
8.4 KiB
C#
264 lines
8.4 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using UnityEngine.SceneManagement;
|
||
using Utils; // 假设此命名空间包含MonoSingleton
|
||
|
||
namespace Base
|
||
{
|
||
public interface ITick
|
||
{
|
||
public void Tick();
|
||
}
|
||
|
||
public interface ITickPhysics
|
||
{
|
||
public void TickPhysics();
|
||
}
|
||
|
||
public interface ITickUI
|
||
{
|
||
public void TickUI();
|
||
}
|
||
|
||
public class Clock : MonoSingleton<Clock>
|
||
{
|
||
private bool _pause = false;
|
||
public bool Pause
|
||
{
|
||
get => _pause;
|
||
set
|
||
{
|
||
if (value != _pause) // 逻辑修改说明:避免重复设置Time.timeScale
|
||
{
|
||
Time.timeScale = value ? 0 : 1;
|
||
_pause = value;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 修改点 1.1:主列表用于迭代
|
||
private readonly List<ITick> _ticks = new();
|
||
private readonly List<ITickPhysics> _tickPhysics = new();
|
||
private readonly List<ITickUI> _tickUIs = new();
|
||
|
||
// 修改点 1.1:缓冲列表用于添加
|
||
private readonly HashSet<ITick> _ticksToAdd = new(); // 逻辑修改说明:使用HashSet避免重复添加,提高查找效率
|
||
private readonly HashSet<ITickPhysics> _tickPhysicsToAdd = new();
|
||
private readonly HashSet<ITickUI> _tickUIsToAdd = new();
|
||
|
||
// 修改点 1.1:缓冲列表用于移除
|
||
private readonly HashSet<ITick> _ticksToRemove = new(); // 逻辑修改说明:使用HashSet避免重复移除,提高查找效率
|
||
private readonly HashSet<ITickPhysics> _tickPhysicsToRemove = new();
|
||
private readonly HashSet<ITickUI> _tickUIsToRemove = new();
|
||
|
||
private void Update()
|
||
{
|
||
// 逻辑修改说明:UI部分的Tick不应受_pause影响
|
||
if (!_pause)
|
||
{
|
||
// 逻辑修改说明:迭代时使用只读副本或确保不会被修改
|
||
// 这里是直接迭代_ticks,确保_ticks在Update生命周期内不会被Add/Remove直接修改
|
||
// 添加和移除操作通过缓冲区在LateUpdate处理
|
||
foreach (var tick in _ticks)
|
||
{
|
||
tick.Tick();
|
||
}
|
||
}
|
||
// UI更新通常不受游戏暂停影响(例如菜单动画、UI计时器等),除非UI本身也需要暂停逻辑。
|
||
// 根据需求决定是否受_pause影响。此处假设UI不暂停。
|
||
foreach (var uiTick in _tickUIs)
|
||
{
|
||
uiTick.TickUI();
|
||
}
|
||
}
|
||
|
||
private void FixedUpdate()
|
||
{
|
||
if (!_pause)
|
||
{
|
||
foreach (var physicsTick in _tickPhysics)
|
||
{
|
||
physicsTick.TickPhysics();
|
||
}
|
||
}
|
||
}
|
||
|
||
// 修改点 1.4:在LateUpdate应用缓冲区的更改
|
||
private void LateUpdate()
|
||
{
|
||
ApplyBufferedChanges();
|
||
}
|
||
|
||
// 修改点 3.1:OnDestroy保持不变,确保事件移除
|
||
private void OnDestroy()
|
||
{
|
||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||
}
|
||
|
||
// 修改点 3.1:OnStart保持不变,负责事件注册和初始化
|
||
protected override void OnStart() // MonoSingleton的Awake后调用
|
||
{
|
||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||
// 逻辑修改说明:Initial清理所有列表,而不是填充
|
||
Init();
|
||
}
|
||
|
||
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||
{
|
||
Init();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化/重置方法。清空所有注册列表和缓冲列表。
|
||
/// </summary>
|
||
// 修改点 2.1:Init() 方法不再负责FindObjectsByType
|
||
public void Init()
|
||
{
|
||
_ticks.Clear();
|
||
_tickPhysics.Clear();
|
||
_tickUIs.Clear();
|
||
|
||
_ticksToAdd.Clear();
|
||
_tickPhysicsToAdd.Clear();
|
||
_tickUIsToAdd.Clear();
|
||
|
||
_ticksToRemove.Clear();
|
||
_tickPhysicsToRemove.Clear();
|
||
_tickUIsToRemove.Clear();
|
||
|
||
// 逻辑修改说明:移除 FindObjectsByType 逻辑
|
||
// 对象应通过其各自的 OnEnable/OnDisable 生命周期来注册/反注册
|
||
foreach (var obj in FindObjectsByType<MonoBehaviour>(FindObjectsSortMode.None))
|
||
{
|
||
if (obj is ITick tickObj) _ticks.Add(tickObj);
|
||
if (obj is ITickPhysics physicsObj) _tickPhysics.Add(physicsObj);
|
||
if (obj is ITickUI uiObj) _tickUIs.Add(uiObj);
|
||
}
|
||
}
|
||
|
||
// 修改点 1.2 & 1.3:将更改放入缓冲,并在LateUpdate统一处理
|
||
public static void AddTick(ITick tick)
|
||
{
|
||
if (Instance != null && tick != null) // 逻辑修改说明:添加null检查
|
||
{
|
||
Instance._ticksToAdd.Add(tick);
|
||
Instance._ticksToRemove.Remove(tick); // 逻辑修改说明:如果在待移除列表,则先移除
|
||
}
|
||
}
|
||
|
||
public static void RemoveTick(ITick tick)
|
||
{
|
||
if (Instance != null && tick != null) // 逻辑修改说明:添加null检查
|
||
{
|
||
Instance._ticksToRemove.Add(tick);
|
||
Instance._ticksToAdd.Remove(tick); // 逻辑修改说明:如果在待添加列表,则先移除
|
||
}
|
||
}
|
||
|
||
public static void AddTickPhysics(ITickPhysics physics)
|
||
{
|
||
if (Instance != null && physics != null)
|
||
{
|
||
Instance._tickPhysicsToAdd.Add(physics);
|
||
Instance._tickPhysicsToRemove.Remove(physics);
|
||
}
|
||
}
|
||
|
||
public static void RemoveTickPhysics(ITickPhysics physics)
|
||
{
|
||
if (Instance != null && physics != null)
|
||
{
|
||
Instance._tickPhysicsToRemove.Add(physics);
|
||
Instance._tickPhysicsToAdd.Remove(physics);
|
||
}
|
||
}
|
||
|
||
public static void AddTickUI(ITickUI ui)
|
||
{
|
||
if (Instance != null && ui != null)
|
||
{
|
||
Instance._tickUIsToAdd.Add(ui);
|
||
Instance._tickUIsToRemove.Remove(ui);
|
||
}
|
||
}
|
||
|
||
public static void RemoveTickUI(ITickUI ui)
|
||
{
|
||
if (Instance != null && ui != null)
|
||
{
|
||
Instance._tickUIsToRemove.Add(ui);
|
||
Instance._tickUIsToAdd.Remove(ui);
|
||
}
|
||
}
|
||
|
||
// 修改点 1.3:应用缓冲区的更改
|
||
private void ApplyBufferedChanges()
|
||
{
|
||
// 先处理移除
|
||
if (_ticksToRemove.Count > 0)
|
||
{
|
||
foreach (var tick in _ticksToRemove)
|
||
{
|
||
_ticks.Remove(tick);
|
||
}
|
||
_ticksToRemove.Clear();
|
||
}
|
||
|
||
if (_tickPhysicsToRemove.Count > 0)
|
||
{
|
||
foreach (var physicsTick in _tickPhysicsToRemove)
|
||
{
|
||
_tickPhysics.Remove(physicsTick);
|
||
}
|
||
_tickPhysicsToRemove.Clear();
|
||
}
|
||
|
||
if (_tickUIsToRemove.Count > 0)
|
||
{
|
||
foreach (var uiTick in _tickUIsToRemove)
|
||
{
|
||
_tickUIs.Remove(uiTick);
|
||
}
|
||
_tickUIsToRemove.Clear();
|
||
}
|
||
|
||
// 后处理添加
|
||
if (_ticksToAdd.Count > 0)
|
||
{
|
||
foreach (var tick in _ticksToAdd)
|
||
{
|
||
if (!_ticks.Contains(tick)) // 逻辑修改说明:避免重复添加到主列表
|
||
{
|
||
_ticks.Add(tick);
|
||
}
|
||
}
|
||
_ticksToAdd.Clear();
|
||
}
|
||
|
||
if (_tickPhysicsToAdd.Count > 0)
|
||
{
|
||
foreach (var physicsTick in _tickPhysicsToAdd)
|
||
{
|
||
if (!_tickPhysics.Contains(physicsTick))
|
||
{
|
||
_tickPhysics.Add(physicsTick);
|
||
}
|
||
}
|
||
_tickPhysicsToAdd.Clear();
|
||
}
|
||
|
||
if (_tickUIsToAdd.Count > 0)
|
||
{
|
||
foreach (var uiTick in _tickUIsToAdd)
|
||
{
|
||
if (!_tickUIs.Contains(uiTick))
|
||
{
|
||
_tickUIs.Add(uiTick);
|
||
}
|
||
}
|
||
_tickUIsToAdd.Clear();
|
||
}
|
||
}
|
||
}
|
||
}
|