目前为止,我们已经有了单例、基于Mono的单例、对象池、事件系统四个轮子(工具),还需要继续造一些常用的工具。
一直以来主流的观点是能不继承MonoBehaviour就不要继承,有关这件事的讨论在这里比较详尽。
因此这里唐老师也是做了一个Mono类,来满足普通类的Update需求工具,本人稍作修改。
这里说个题外话,有很多人会在架构阶段就设计成除了一个Mono类,其他全都不继承Mono的极端想法,主要是为了考虑性能问题。个人觉得性能98%都是受美术的影响,而非程序,程序内部主要管控好:加载、实例化、不要在各种Update中调用太消耗性能的东西,循环中的操作不要太复杂,数学运算尽可能提高效率,避免运行时使用反射等,代码的效率优化就足够了。而非要为了不继承Mono,用一个类的Update来调用全局的类刷新,个人感觉就是在脱裤子放屁,毫无意义。
因此我们这里仅把Mono作为一个工具类,来弥补普通类无法Update的问题。
还是先看用法,很简单,添加一个监听,即可实现Update调用Log:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Main : MonoBehaviour
{
private void Start()
{
//直接增加监听,参数也可以是个Action
MonoUtil.Instance.AddUpdateListener(Log);
//调用协程的案例
MonoUtil.Instance.StartCoroutine(RemoveLogListener());
//另外此处将常用的延迟执行功能,做成了一个简单函数调用方式
MonoUtil.Instance.Delay(1, () => Debug.Log("Delay结束1"));
MonoUtil.Instance.Delay(2, () => Debug.Log("Delay结束2"));
MonoUtil.Instance.Delay(3, () => Debug.Log("Delay结束3"));
}
void Log()
{
Debug.Log("测试输出");
}
IEnumerator RemoveLogListener()
{
yield return new WaitForSeconds(1);
MonoUtil.Instance.RemoveUpdateListener(Log);
Debug.Log("测试结束");
}
}
可以看到正确地调用到了Log函数和协程:
image.png
Mono工具类脚本如下(基于MonoSingleton):
using System;
using System.Collections;
using UnityEngine;
/// <summary>
/// Mono工具类
/// </summary>
public class MonoUtil : MonoSingleton<MonoUtil>
{
/// <summary>
/// 创建委托事件
/// </summary>
private event Action m_UpdateAction;
void Start()
{
//不让该对象移除
DontDestroyOnLoad(this.gameObject);
}
void Update()
{
if (m_UpdateAction != null)
m_UpdateAction();
}
/// <summary>
/// 添加帧更新监听
/// </summary>
/// <param name="func"></param>
public void AddUpdateListener(Action action)
{
m_UpdateAction += action;
}
/// <summary>
/// 移除帧更新监听
/// </summary>
/// <param name="func"></param>
public void RemoveUpdateListener(Action action)
{
m_UpdateAction -= action;
}
/// <summary>
/// 延迟几秒执行
/// </summary>
/// <param name="seconds">秒数</param>
/// <param name="onFinished">回调</param>
public void Delay(float seconds, Action action)
{
StartCoroutine(DelayCoroutine(seconds, action));
}
//延迟几秒回调协程
private static IEnumerator DelayCoroutine(float seconds, Action action)
{
yield return new WaitForSeconds(seconds);
action();
}
}
网友评论