初学者,自用笔记

基于事件中心

// Mono控制器:提供生命周期事件监听和协程管理功能
public class MonoController : MonoBehaviour
{
    // 无参Update事件委托
    private event Action updateEvent;

    // 协程字典:存储协程标识与对应协程引用,用于精准管理协程
    private Dictionary<string, Coroutine> _coroutineDict = new Dictionary<string, Coroutine>();

    public static MonoController Instace;

    private void Awake()
    {
        Instace = this;
    }

    void Start()
    {
        
    }

    // Unity每帧执行:触发注册的Update事件
    void Update()
    {
        if(updateEvent!=null)
        {
            updateEvent();
        }
    }

    // 启动协程(带标识):避免重复启动同名协程
    public void StartCoroutineEx(string key, IEnumerator routine)
    {
        // 若已存在同名协程,先停止再重启
        if (_coroutineDict.ContainsKey(key))
        {
            StopCoroutineEx(key);
        }
        // 存储协程引用并启动
        _coroutineDict[key] = StartCoroutine(routine);
    }

    // 停止指定标识的协程:并清理字典记录
    public void StopCoroutineEx(string key)
    {
        if (_coroutineDict.TryGetValue(key, out Coroutine coroutine))
        {
            StopCoroutine(coroutine);    // 停止协程
            _coroutineDict.Remove(key);  // 移除无效记录
        }
    }

    // 添加Update事件监听
    public void AddUpdateListener(Action _fun)
    {
        updateEvent += _fun;
    }

    // 移除Update事件监听
    public void RemoveUpdateListener(Action _fun)
    {
        updateEvent -= _fun;
    }
}

基于接口


// 执行接口,方便进行依赖注入
public interface IUpdateLoop
{
    void RegisterUpdate(IUpdateable u);
    void UnregisterUpdate(IUpdateable u);

    void RegisterFixed(IFixedUpdateable f);
    void UnregisterFixed(IFixedUpdateable f);
}

public interface ICoroutineRunner
{
    void StartCoroutineEx(string key, IEnumerator routine);
    void StopCoroutineEx(string key);
    void StopCoroutinesByPrefix(string prefix);
}

// 使用方,帧更新接口
public interface IUpdateable { void OnUpdate(); }
// 使用方,物理帧更新接口
public interface IFixedUpdateable { void OnFixedUpdate(); }

public class MonoController : MonoBehaviour
{
  
    public static MonoController Instance { get; private set; }

    [SerializeField] private MonoController myMono;
  
     // 存储需要帧更新的实例(IUpdateable)
    private List<IUpdateable> _updateables = new List<IUpdateable>();
    // 存储需要物理帧更新的实例(IFixedUpdateable)
    private List<IFixedUpdateable> _fixedUpdateables = new List<IFixedUpdateable>();

    // 协程管理字典
    private Dictionary<string, Coroutine> _coroutineDict = new Dictionary<string, Coroutine>();

    #region Update
    public void RegisterUpdate(IUpdateable updateable)
    {
        if (updateable != null && !_updateables.Contains(updateable))
        {
            _updateables.Add(updateable);
        }
    }

    public void UnregisterUpdate(IUpdateable updateable)
    {
        if (_updateables.Contains(updateable))
        {
            _updateables.Remove(updateable);
        }
    }
    #endregion

    #region FixedUpdate
    public void RegisterFixedUpdate(IFixedUpdateable fixedUpdateable)
    {
        if (fixedUpdateable != null && !_fixedUpdateables.Contains(fixedUpdateable))
        {
            _fixedUpdateables.Add(fixedUpdateable);
        }
    }

    public void UnregisterFixedUpdate(IFixedUpdateable fixedUpdateable)
    {
        if (_fixedUpdateables.Contains(fixedUpdateable))
        {
            _fixedUpdateables.Remove(fixedUpdateable);
        }
    }
    #endregion

    #region 协程管理
    public void StartCoroutineEx(string key, IEnumerator routine)
    {
        if (string.IsNullOrEmpty(key) || routine == null) return;

        if (_coroutineDict.ContainsKey(key))
        {
            StopCoroutineEx(key);
        }
        _coroutineDict[key] = StartCoroutine(routine);
    }

    public void StopCoroutineEx(string key)
    {
        if (string.IsNullOrEmpty(key)) return;

        if (_coroutineDict.TryGetValue(key, out Coroutine coroutine))
        {
            StopCoroutine(coroutine);
            _coroutineDict.Remove(key);
        }
    }

    // 停止所有以指定前缀开头的协程
    public void StopCoroutinesByPrefix(string prefix)
    {
        if (string.IsNullOrEmpty(prefix)) return;

        var keysToRemove = new List<string>();
        foreach (var kvp in _coroutineDict)
        {
            if (kvp.Key.StartsWith(prefix))
            {
                StopCoroutine(kvp.Value);
                keysToRemove.Add(kvp.Key);
            }
        }
        foreach (var key in keysToRemove)
        {
            _coroutineDict.Remove(key);
        }
    }
    #endregion

    #region Unity 生命周期 统一驱动
    private void Update()
    {
        for (int i = 0; i < _updateables.Count; i++)
        {
            _updateables[i]?.OnUpdate(); 
        }
    }

    private void FixedUpdate()
    {
        for (int i = 0; i < _fixedUpdateables.Count; i++)
        {
            _fixedUpdateables[i]?.OnFixedUpdate();
        }
    }
    #endregion

    // 清理无效引用(场景切换/对象销毁时调用,避免冗余)
    public void CleanupInvalid()
    {
        _updateables.RemoveAll(item => item == null);
        _fixedUpdateables.RemoveAll(item => item == null);
        _coroutineDict.Clear();
    }
}

优化

待更新-unitask相关

// 保持接口定义
public interface IUpdateable { void OnUpdate(); }
public interface IFixedUpdateable { void OnFixedUpdate(); }

public static class MonoController
{
    // 内部驱动组件,隐藏实现
    private class MonoDriver : MonoBehaviour
    {
        // Update 相关(双缓冲队列保证遍历安全)
       //双缓冲队列的核心思想是:把 “遍历过程中” 的增删操作暂时缓存,等遍历结束后再统一执行
        private readonly List<IUpdateable> _updateables = new List<IUpdateable>(1024);
        private readonly List<IUpdateable> _pendingAddUpdate = new List<IUpdateable>(128);
        private readonly List<IUpdateable> _pendingRemoveUpdate = new List<IUpdateable>(128);
        private bool _isUpdating;

        // FixedUpdate 相关
        private readonly List<IFixedUpdateable> _fixedUpdateables = new List<IFixedUpdateable>(1024);
        private readonly List<IFixedUpdateable> _pendingAddFixed = new List<IFixedUpdateable>(128);
        private readonly List<IFixedUpdateable> _pendingRemoveFixed = new List<IFixedUpdateable>(128);
        private bool _isFixedUpdating;

        #region Update 管理
        public void RegisterUpdate(IUpdateable updateable)
        {
            if (updateable == null) return;
            if (_isUpdating)
                _pendingAddUpdate.Add(updateable);
            else if (!_updateables.Contains(updateable))
                _updateables.Add(updateable);
        }

        public void UnregisterUpdate(IUpdateable updateable)
        {
            if (updateable == null) return;
            if (_isUpdating)
                _pendingRemoveUpdate.Add(updateable);
            else
                _updateables.Remove(updateable);
        }
        #endregion

        #region FixedUpdate 管理
        public void RegisterFixedUpdate(IFixedUpdateable fixedUpdateable)
        {
            if (fixedUpdateable == null) return;
            if (_isFixedUpdating)
                _pendingAddFixed.Add(fixedUpdateable);
            else if (!_fixedUpdateables.Contains(fixedUpdateable))
                _fixedUpdateables.Add(fixedUpdateable);
        }

        public void UnregisterFixedUpdate(IFixedUpdateable fixedUpdateable)
        {
            if (fixedUpdateable == null) return;
            if (_isFixedUpdating)
                _pendingRemoveFixed.Add(fixedUpdateable);
            else
                _fixedUpdateables.Remove(fixedUpdateable);
        }
        #endregion

        #region Unity 生命周期
        private void Update()
        {
            _isUpdating = true;
            // 执行 Update 逻辑
            for (int i = 0; i < _updateables.Count; i++)
            {
                _updateables[i]?.OnUpdate();
            }
            _isUpdating = false;

            // 处理缓冲队列
            ProcessPendingUpdate();
        }

        private void FixedUpdate()
        {
            _isFixedUpdating = true;
            // 执行 FixedUpdate 逻辑
            for (int i = 0; i < _fixedUpdateables.Count; i++)
            {
                _fixedUpdateables[i]?.OnFixedUpdate();
            }
            _isFixedUpdating = false;

            // 处理缓冲队列
            ProcessPendingFixed();
        }
        #endregion

        #region 缓冲队列处理
        private void ProcessPendingUpdate()
        {
            // 新增
            if (_pendingAddUpdate.Count > 0)
            {
                foreach (var item in _pendingAddUpdate)
                {
                    if (!_updateables.Contains(item))
                        _updateables.Add(item);
                }
                _pendingAddUpdate.Clear();
            }
            // 移除
            if (_pendingRemoveUpdate.Count > 0)
            {
                foreach (var item in _pendingRemoveUpdate)
                {
                    _updateables.Remove(item);
                }
                _pendingRemoveUpdate.Clear();
            }
            // 清理空引用
            _updateables.RemoveAll(item => item == null);
        }

        private void ProcessPendingFixed()
        {
            // 新增
            if (_pendingAddFixed.Count > 0)
            {
                foreach (var item in _pendingAddFixed)
                {
                    if (!_fixedUpdateables.Contains(item))
                        _fixedUpdateables.Add(item);
                }
                _pendingAddFixed.Clear();
            }
            // 移除
            if (_pendingRemoveFixed.Count > 0)
            {
                foreach (var item in _pendingRemoveFixed)
                {
                    _fixedUpdateables.Remove(item);
                }
                _pendingRemoveFixed.Clear();
            }
            // 清理空引用
            _fixedUpdateables.RemoveAll(item => item == null);
        }
        #endregion

        // 外部调用的清理方法
        public void CleanupAll()
        {
            _updateables.Clear();
            _pendingAddUpdate.Clear();
            _pendingRemoveUpdate.Clear();

            _fixedUpdateables.Clear();
            _pendingAddFixed.Clear();
            _pendingRemoveFixed.Clear();
        }
    }

    // 内部驱动实例
    private static MonoDriver _driver;

    // 自动初始化(场景加载前创建)
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    private static void Initialize()
    {
        if (_driver == null)
        {
            GameObject go = new GameObject("[Framework_MonoController]");
            _driver = go.AddComponent<MonoDriver>();
            GameObject.DontDestroyOnLoad(go);
        }
    }

    // 对外暴露的静态 API
    public static void RegisterUpdate(IUpdateable updateable) => _driver.RegisterUpdate(updateable);
    public static void UnregisterUpdate(IUpdateable updateable) => _driver.UnregisterUpdate(updateable);

    public static void RegisterFixedUpdate(IFixedUpdateable fixedUpdateable) => _driver.RegisterFixedUpdate(fixedUpdateable);
    public static void UnregisterFixedUpdate(IFixedUpdateable fixedUpdateable) => _driver.UnregisterFixedUpdate(fixedUpdateable);

    public static void CleanupAll() => _driver.CleanupAll();
}