初学者,自用笔记

基于事件中心

// 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
{
    [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();
    }
}