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的生命周期函数。
步骤说明:
- 创建一个继承自
Singleton<T>
的类(不继承MonoBehaviour) - 在类中定义Update方法和协程方法
- 通过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的功能。
步骤说明:
- 创建MonoBehaviour测试脚本
- 在Start方法中调用ExternalLogicProcessor的方法
- 验证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的生命周期事件管理功能。
步骤说明:
- 创建MonoBehaviour测试脚本
- 同时监听Update、FixedUpdate、LateUpdate事件
- 测试动态移除事件监听器
- 在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