3.公共Mono模块

3.公共Mono模块


3.1 知识点

公共Mono模块的作用



公共Mono模块的基本原理

实现公共Mono模块

基于框架的实际实现,我们创建一个继承自自动挂载式单例的MonoMgr类,提供统一的生命周期函数和协程管理。

源码实现:MonoMgr.cs

using UnityEngine.Events;

/// <summary>
/// 公共Mono模块管理器
/// 提供统一的Update、FixedUpdate、LateUpdate事件管理和协程管理
/// 让不继承MonoBehaviour的类也能使用Unity生命周期函数和协程功能
/// </summary>
public class MonoMgr : SingletonAutoMono<MonoMgr>
{
    #region 字段

    /// <summary>
    /// Update事件委托
    /// </summary>
    private event UnityAction UpdateEvent;

    /// <summary>
    /// FixedUpdate事件委托
    /// </summary>
    private event UnityAction FixedUpdateEvent;

    /// <summary>
    /// LateUpdate事件委托
    /// </summary>
    private event UnityAction LateUpdateEvent;

    #endregion

    #region Update相关方法

    /// <summary>
    /// 添加Update帧更新事件监听器
    /// </summary>
    /// <param name="updateFun">要添加的Update更新函数</param>
    public void AddUpdateListener(UnityAction updateFun)
    {
        UpdateEvent += updateFun;
    }

    /// <summary>
    /// 移除Update帧更新事件监听器
    /// </summary>
    /// <param name="updateFun">要移除的Update更新函数</param>
    public void RemoveUpdateListener(UnityAction updateFun)
    {
        UpdateEvent -= updateFun;
    }

    /// <summary>
    /// 添加FixedUpdate帧更新事件监听器
    /// </summary>
    /// <param name="updateFun">要添加的FixedUpdate更新函数</param>
    public void AddFixedUpdateListener(UnityAction updateFun)
    {
        FixedUpdateEvent += updateFun;
    }

    /// <summary>
    /// 移除FixedUpdate帧更新事件监听器
    /// </summary>
    /// <param name="updateFun">要移除的FixedUpdate更新函数</param>
    public void RemoveFixedUpdateListener(UnityAction updateFun)
    {
        FixedUpdateEvent -= updateFun;
    }

    /// <summary>
    /// 添加LateUpdate帧更新事件监听器
    /// </summary>
    /// <param name="updateFun">要添加的LateUpdate更新函数</param>
    public void AddLateUpdateListener(UnityAction updateFun)
    {
        LateUpdateEvent += updateFun;
    }

    /// <summary>
    /// 移除LateUpdate帧更新事件监听器
    /// </summary>
    /// <param name="updateFun">要移除的LateUpdate更新函数</param>
    public void RemoveLateUpdateListener(UnityAction updateFun)
    {
        LateUpdateEvent -= updateFun;
    }

    #endregion

    #region Unity生命周期

    private void Update()
    {
        UpdateEvent?.Invoke();
    }

    private void FixedUpdate()
    {
        FixedUpdateEvent?.Invoke();
    }

    private void LateUpdate()
    {
        LateUpdateEvent?.Invoke();
    }

    #endregion
}

测试和使用

创建不继承MonoBehaviour的管理器类

首先,我们需要创建一个不继承MonoBehaviour的管理器类,让它通过MonoMgr来使用Unity的生命周期函数。

步骤说明:

  1. 创建一个继承自Singleton<T>的类(不继承MonoBehaviour)
  2. 在类中定义Update方法和协程方法
  3. 通过MonoMgr注册Update监听器和启动协程

测试代码:

// 创建一个不继承MonoBehaviour的管理器类
public class ExternalLogicProcessor : Singleton<ExternalLogicProcessor>
{
    private Coroutine testCoroutine;
    private bool isUpdating = false;

    // 私有构造函数,保证单例唯一性
    private ExternalLogicProcessor()
    {
        Debug.Log("外部逻辑处理器:构造函数被调用");
    }

    // 启动逻辑的方法
    public void StartLogic()
    {
        Debug.Log("外部逻辑处理器:开始逻辑(Update监听器和协程)");
        
        // 通过MonoMgr添加Update监听器
        MonoMgr.Instance.AddUpdateListener(MyUpdate);
        isUpdating = true;

        // 通过MonoMgr启动协程
        testCoroutine = MonoMgr.Instance.StartCoroutine(MyCoroutine());
    }

    // 停止逻辑的方法
    public void StopLogic()
    {
        Debug.Log("外部逻辑处理器:停止逻辑(Update监听器和协程)");
        
        // 移除Update监听器
        MonoMgr.Instance.RemoveUpdateListener(MyUpdate);
        isUpdating = false;

        // 停止协程
        if (testCoroutine != null)
        {
            MonoMgr.Instance.StopCoroutine(testCoroutine);
            testCoroutine = null;
        }
    }

    // Update方法(通过MonoMgr调用)
    private void MyUpdate()
    {
        if (isUpdating)
        {
            Debug.Log("外部逻辑处理器:MyUpdate每帧被调用");
        }
    }

    // 协程方法
    private IEnumerator MyCoroutine()
    {
        int count = 0;
        while (true)
        {
            Debug.Log($"外部逻辑处理器:协程运行中,计数:{count++}");
            yield return new WaitForSeconds(1f);
        }
    }
}

创建测试脚本验证功能

创建一个MonoBehaviour脚本来测试ExternalLogicProcessor的功能。

步骤说明:

  1. 创建MonoBehaviour测试脚本
  2. 在Start方法中调用ExternalLogicProcessor的方法
  3. 验证Update和协程是否正常工作

测试代码:

// 创建测试脚本
public class MonoMgrUsageTest : MonoBehaviour
{
    void Start()
    {
        Debug.Log("MonoMgr使用测试:开始");

        // 测试不继承MonoBehaviour的类如何使用MonoMgr
        ExternalLogicProcessor.Instance.StartLogic();
        // 输出:外部逻辑处理器:构造函数被调用
        // 输出:外部逻辑处理器:开始逻辑(Update监听器和协程)
        // 输出:外部逻辑处理器:MyUpdate每帧被调用(每帧)
        // 输出:外部逻辑处理器:协程运行中,计数:0(1秒后)

        // 延迟3秒后停止逻辑
        Invoke("StopExternalLogic", 3f);
    }

    private void StopExternalLogic()
    {
        Debug.Log("MonoMgr使用测试:停止外部逻辑处理器的逻辑");
        ExternalLogicProcessor.Instance.StopLogic();
        // 输出:外部逻辑处理器:停止逻辑(Update监听器和协程)
        // 结果:Update输出和协程执行停止
    }

    void OnDestroy()
    {
        // 确保在测试脚本销毁时,停止所有MonoMgr管理的协程
        MonoMgr.Instance.StopAllCoroutines();
        Debug.Log("MonoMgr使用测试:OnDestroy,所有MonoMgr协程已停止");
    }
}

测试生命周期事件管理

创建一个测试脚本来验证MonoMgr的生命周期事件管理功能。

步骤说明:

  1. 创建MonoBehaviour测试脚本
  2. 同时监听Update、FixedUpdate、LateUpdate事件
  3. 测试动态移除事件监听器
  4. 在OnDestroy中清理所有监听器

测试代码:

// 生命周期事件测试脚本
public class LifecycleEventTest : MonoBehaviour
{
    private string logTag = "生命周期事件测试";

    void Start()
    {
        Debug.Log($"{logTag}:开始");

        // 添加Update事件监听
        MonoMgr.Instance.AddUpdateListener(OnUpdateEvent);
        // 添加FixedUpdate事件监听
        MonoMgr.Instance.AddFixedUpdateListener(OnFixedUpdateEvent);
        // 添加LateUpdate事件监听
        MonoMgr.Instance.AddLateUpdateListener(OnLateUpdateEvent);

        // 延迟5秒后移除Update监听
        Invoke("RemoveUpdateListener", 5f);
    }

    private void OnUpdateEvent()
    {
        Debug.Log($"{logTag}:OnUpdateEvent被调用");
        // 输出:生命周期事件测试:OnUpdateEvent被调用(每帧)
    }

    private void OnFixedUpdateEvent()
    {
        Debug.Log($"{logTag}:OnFixedUpdateEvent被调用");
        // 输出:生命周期事件测试:OnFixedUpdateEvent被调用(固定时间间隔)
    }

    private void OnLateUpdateEvent()
    {
        Debug.Log($"{logTag}:OnLateUpdateEvent被调用");
        // 输出:生命周期事件测试:OnLateUpdateEvent被调用(每帧,在Update之后)
    }

    private void RemoveUpdateListener()
    {
        Debug.Log($"{logTag}:移除Update监听器");
        MonoMgr.Instance.RemoveUpdateListener(OnUpdateEvent);
        // 结果:OnUpdateEvent将不再被调用,其他事件继续
    }

    void OnDestroy()
    {
        Debug.Log($"{logTag}:OnDestroy");
        // 确保移除所有监听器,避免内存泄露
        MonoMgr.Instance.RemoveUpdateListener(OnUpdateEvent);
        MonoMgr.Instance.RemoveFixedUpdateListener(OnFixedUpdateEvent);
        MonoMgr.Instance.RemoveLateUpdateListener(OnLateUpdateEvent);
    }
}

3.2 知识点代码

MonoMgr.cs(公共Mono模块管理器)

using UnityEngine.Events;

/// <summary>
/// 公共Mono模块管理器
/// 提供统一的Update、FixedUpdate、LateUpdate事件管理和协程管理
/// 让不继承MonoBehaviour的类也能使用Unity生命周期函数和协程功能
/// </summary>
public class MonoMgr : SingletonAutoMono<MonoMgr>
{
    #region 字段

    /// <summary>
    /// Update事件委托
    /// </summary>
    private event UnityAction UpdateEvent;

    /// <summary>
    /// FixedUpdate事件委托
    /// </summary>
    private event UnityAction FixedUpdateEvent;

    /// <summary>
    /// LateUpdate事件委托
    /// </summary>
    private event UnityAction LateUpdateEvent;

    #endregion

    #region Update相关方法

    /// <summary>
    /// 添加Update帧更新事件监听器
    /// </summary>
    /// <param name="updateFun">要添加的Update更新函数</param>
    public void AddUpdateListener(UnityAction updateFun)
    {
        UpdateEvent += updateFun;
    }

    /// <summary>
    /// 移除Update帧更新事件监听器
    /// </summary>
    /// <param name="updateFun">要移除的Update更新函数</param>
    public void RemoveUpdateListener(UnityAction updateFun)
    {
        UpdateEvent -= updateFun;
    }

    /// <summary>
    /// 添加FixedUpdate帧更新事件监听器
    /// </summary>
    /// <param name="updateFun">要添加的FixedUpdate更新函数</param>
    public void AddFixedUpdateListener(UnityAction updateFun)
    {
        FixedUpdateEvent += updateFun;
    }

    /// <summary>
    /// 移除FixedUpdate帧更新事件监听器
    /// </summary>
    /// <param name="updateFun">要移除的FixedUpdate更新函数</param>
    public void RemoveFixedUpdateListener(UnityAction updateFun)
    {
        FixedUpdateEvent -= updateFun;
    }

/// <summary>
    /// 添加LateUpdate帧更新事件监听器
/// </summary>
    /// <param name="updateFun">要添加的LateUpdate更新函数</param>
    public void AddLateUpdateListener(UnityAction updateFun)
    {
        LateUpdateEvent += updateFun;
    }

    /// <summary>
    /// 移除LateUpdate帧更新事件监听器
    /// </summary>
    /// <param name="updateFun">要移除的LateUpdate更新函数</param>
    public void RemoveLateUpdateListener(UnityAction updateFun)
    {
        LateUpdateEvent -= updateFun;
    }

    #endregion

    #region Unity生命周期

    private void Update()
    {
        UpdateEvent?.Invoke();
    }

    private void FixedUpdate()
    {
        FixedUpdateEvent?.Invoke();
    }

    private void LateUpdate()
    {
        LateUpdateEvent?.Invoke();
    }

    #endregion
}

ExternalLogicProcessor.cs(不继承Mono的逻辑处理器)

using System.Collections;
using UnityEngine;

// 不继承MonoBehaviour的管理器类,演示如何通过MonoMgr使用Update和协程
public class ExternalLogicProcessor : Singleton<ExternalLogicProcessor>
{
    private Coroutine testCoroutine;
    private bool isUpdating = false;

    // 私有构造函数,保证单例唯一性
    private ExternalLogicProcessor()
    {
        Debug.Log("外部逻辑处理器:构造函数被调用");
    }

    public void StartLogic()
    {
        Debug.Log("外部逻辑处理器:开始逻辑(Update监听器和协程)");
        // 添加Update监听器
        MonoMgr.Instance.AddUpdateListener(MyUpdate);
        isUpdating = true;

        // 启动协程
        testCoroutine = MonoMgr.Instance.StartCoroutine(MyCoroutine());
    }

    public void StopLogic()
    {
        Debug.Log("外部逻辑处理器:停止逻辑(Update监听器和协程)");
        // 移除Update监听器
        MonoMgr.Instance.RemoveUpdateListener(MyUpdate);
        isUpdating = false;

        // 停止协程
        if (testCoroutine != null)
        {
            MonoMgr.Instance.StopCoroutine(testCoroutine);
            testCoroutine = null;
        }
    }

    private IEnumerator MyCoroutine()
    {
        int count = 0;
        while (true)
        {
            Debug.Log($"外部逻辑处理器:协程运行中,计数:{count++}");
            yield return new WaitForSeconds(1f);
        }
    }

    private void MyUpdate()
    {
        if (isUpdating)
        {
            Debug.Log("外部逻辑处理器:MyUpdate每帧被调用");
        }
    }
}

MonoMgrUsageTest.cs(MonoMgr功能使用测试)

using UnityEngine;

// 用于在Unity场景中测试ExternalLogicProcessor和MonoMgr的交互
public class MonoMgrUsageTest : MonoBehaviour
{
    void Start()
    {
        Debug.Log("MonoMgr使用测试:开始");

        // 1. 测试不继承MonoBehaviour的类如何使用MonoMgr
        ExternalLogicProcessor.Instance.StartLogic();
        // 输出:外部逻辑处理器:构造函数被调用
        // 输出:外部逻辑处理器:开始逻辑(Update监听器和协程)
        // 输出:外部逻辑处理器:MyUpdate每帧被调用(每帧)
        // 输出:外部逻辑处理器:协程运行中,计数:0(1秒后)
        // ...

        // 2. 延迟3秒后停止ExternalLogicProcessor的逻辑
        Invoke("StopExternalLogic", 3f);
    }

    private void StopExternalLogic()
    {
        Debug.Log("MonoMgr使用测试:停止外部逻辑处理器的逻辑");
        ExternalLogicProcessor.Instance.StopLogic();
        // 输出:外部逻辑处理器:停止逻辑(Update监听器和协程)
        // 结果:ExternalLogicProcessor的Update和协程将停止输出
    }

    void OnDestroy()
    {
        // 确保在测试脚本销毁时,停止所有MonoMgr管理的协程和事件,避免资源泄露
        // 实际项目中,通常在游戏退出或特定模块卸载时进行清理
        // 注意:ExternalLogicProcessor.Instance.StopLogic() 已经移除了Update监听和停止了协程
        // 这里仅作为额外的清理示例,如果ExternalLogicProcessor实例可能在其他地方被引用,则需要更精细的清理
        MonoMgr.Instance.StopAllCoroutines(); // 停止所有由MonoMgr启动的协程
        Debug.Log("MonoMgr使用测试:OnDestroy,所有MonoMgr协程已停止");
    }
}

LifecycleEventTest.cs(生命周期事件监听测试)

using UnityEngine;

// 演示如何直接监听MonoMgr提供的生命周期事件
public class LifecycleEventTest : MonoBehaviour
{
    private string logTag = "生命周期事件测试";

    void Start()
    {
        Debug.Log($"{logTag}:开始");

        // 添加Update事件监听
        MonoMgr.Instance.AddUpdateListener(OnUpdateEvent);
        // 添加FixedUpdate事件监听
        MonoMgr.Instance.AddFixedUpdateListener(OnFixedUpdateEvent);
        // 添加LateUpdate事件监听
        MonoMgr.Instance.AddLateUpdateListener(OnLateUpdateEvent);

        // 延迟5秒后移除Update监听
        Invoke("RemoveUpdateListener", 5f);
    }

    private void OnUpdateEvent()
    {
        Debug.Log($"{logTag}:OnUpdateEvent被调用");
        // 输出:生命周期事件测试:OnUpdateEvent被调用(每帧)
    }

    private void OnFixedUpdateEvent()
    {
        Debug.Log($"{logTag}:OnFixedUpdateEvent被调用");
        // 输出:生命周期事件测试:OnFixedUpdateEvent被调用(固定时间间隔)
    }

    private void OnLateUpdateEvent()
    {
        Debug.Log($"{logTag}:OnLateUpdateEvent被调用");
        // 输出:生命周期事件测试:OnLateUpdateEvent被调用(每帧,在Update之后)
    }

    private void RemoveUpdateListener()
    {
        Debug.Log($"{logTag}:移除Update监听器");
        MonoMgr.Instance.RemoveUpdateListener(OnUpdateEvent);
        // 结果:OnUpdateEvent将不再被调用
    }

    void OnDestroy()
    {
        Debug.Log($"{logTag}:OnDestroy");
        // 确保移除所有监听器,避免内存泄露
        MonoMgr.Instance.RemoveUpdateListener(OnUpdateEvent);
        MonoMgr.Instance.RemoveFixedUpdateListener(OnFixedUpdateEvent);
        MonoMgr.Instance.RemoveLateUpdateListener(OnLateUpdateEvent);
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏