在日常开发中,我们有时候会遇到不希望继承MonoBehaviour的类,但是我们又会需要去调用MonoBehaviour中的生命周期函数或者是去开启关闭协程。这时我们只需要使用一个管理类对MonoBehaviour进行一层封装,只在需要使用到上述功能的类的内部取调用这个管理类就可以解决问题。下面是对于公共Mono类的实现。
首先声明一个MonoController类用于对MonoBehaviour进行第一层封装。
public class MonoController : MonoBehaviour
{
public event UnityAction updataEvent;
private void Start()
{
DontDestroyOnLoad(this);
}
private void Update()
{
if (updataEvent != null)
updataEvent();
}
/// <summary>
/// 给外部提供的添加帧更新事件的函数
/// </summary>
public void AddUpdateListener(UnityAction action)
{
updataEvent += action;
}
/// <summary>
/// 给外部提供的移除帧更新事件的函数
/// </summary>
/// <param name="action"></param>
public void RemoveUpdateListener(UnityAction action)
{
updataEvent -= action;
}
}
该类虽然继承自MonoController,但是它通过委托事件封装了函数,然后在其Update中去调用这些函数。本质来说就是给外部提供了一个可以在Update中去每帧执行函数的接口。
然后再声明一个单例的MonoManager进行第二层封装。
public class MonoManager : ISingleton
{
public static MonoManager Instance => Singleton<MonoManager>.Instace;
public MonoController controller;
public MonoManager() {
GameObject obj = new GameObject("MonoContorller");
controller = obj.AddComponent<MonoController>();
}
public void Init() { }
/// <summary>
/// 给外部提供的添加帧更新事件的函数
/// </summary>
public void AddUpdateListener(UnityAction action)
{
controller.AddUpdateListener(action);
}
/// <summary>
/// 给外部提供的移除帧更新事件的函数
/// </summary>
/// <param name="action"></param>
public void RemoveUpdateListener(UnityAction action)
{
controller.RemoveUpdateListener(action);
}
/// <summary>
/// 开启协程
/// </summary>
/// <returns></returns>
public Coroutine StartCoroutine(IEnumerator routine) {
return controller.StartCoroutine(routine);
}
/// <summary>
/// 开启协程
/// </summary>
/// <param name="methodName">函数名</param>
/// <param name="value">想要传递的参数</param>
/// <returns></returns>
public Coroutine StartCoroutine(string methodName, [DefaultValue("null")] object value) {
return controller.StartCoroutine(methodName, value);
}
/// <summary>
/// 开启协程
/// </summary>
/// <param name="methodName">函数名</param>
/// <returns></returns>
public Coroutine StartCoroutine(string methodName) {
return controller.StartCoroutine(methodName);
}
//通过string函数名 只能开启controller中的函数
//如果想要通过协程去开启别的脚本中的函数
//则不能使用该方法
}
在场景中生成MonoController游戏对象并且将MonoController添加上去,然后由MonoManager去掌控是否添加委托。并且直接在Manager内部声明返回值为Coroutine的开启协程函数,其本质也是对Mono进行的封装。
使用方法如下:
public class Test
{
public void TestFunc()
{
Debug.Log(111);
}
}
public class TestTest:MonoBehaviour {
Test test =new Test ();
private void Start()
{
MonoManager.Instance.AddUpdateListener(test.TestFunc);
}
}
声明一个Test类,其中有一个方法TestFunc打印111,然后声明一个TestTest类继承字MonoBehaviour,然后在其Start函数对TestFunc进行添加。将TestTest挂载到GameObjet上,最后实现不是继承自MonoBehaviour的类Test中的函数每帧执行。