UFL2——公共Mono模块

前置知识点

  1. 委托,事件(C#四部曲C#进阶中)
  2. 生命周期函数
  3. 协同程序

公共Mono模块

  1. 公共 Mono 模块的主要作用

    1. 让不继承 MonoBehaviour 的脚本也能利用帧更新或定时更新处理逻辑
    2. 让不继承 MonoBehaviour 的脚本也能利用协同程序处理逻辑
    3. 可以统一执行管理 MonoBehaviour 脚本的帧更新或定时更新相关逻辑
  2. 公共Mono模块的基本原理

    1. 通过事件或委托 管理 不继承 MonoBehaviour 脚本的相关更新函数
    2. 提供协同程序开启或关闭的方法

公共Mono模块的主要作用

Unity游戏开发当中,继承 MonoBehaviour​ 的类,可以使用生命周期函数,可以开启协同程序。
我们可以利用生命周期函数中的 Update​、FixedUpdate​、LateUpdate 等函数,进行帧更新或定时更新,用来处理游戏逻辑。
可以利用协同程序分时分步的处理游戏逻辑,比如异步加载,复杂逻辑分步等

但是对于没有继承 MonoBehaviour​ 的脚本,我们无法使用这些内容来处理逻辑。
在不进行任何处理的情况下,我们无法在不继承 MonoBehaviour的脚本中进行帧更新或者定时更新逻辑,也无法利用协同程序分时分步执行逻辑

因此公共Mono模块的主要作用是:让不继承 MonoBehaviour 的脚本也能

  1. 利用帧更新或定时更新处理逻辑
  2. 利用协同程序处理逻辑

除了刚才提到的主要作用,由于Unity当中过多脚本中的过多帧更新或定时更新函数会对性能有一定的影响
在满足主要作用的同时,我们还可以对它们进行集中化管理减少Unity中多脚本中帧更新或定时更新函数的数量,从而来提升一定的性能

公共Mono模块的基本原理

实现一个 继承 继承MonoBehaviour单例模式基类 的公共 Mono 管理器脚本,在其中

  1. 通过事件或委托 管理 不继承 MonoBehaviour 脚本的相关更新函数
  2. 提供协同程序开启或关闭的方法

从而达到我们的目的

让不继承 MonoBehaviour 的脚本也能

  1. 利用帧更新或定时更新处理逻辑
  2. 利用协同程序处理逻辑
  3. 可以统一执行管理帧更新或定时更新相关逻辑

公共 Mono 模块的具体实现

  1. 创建 MonoManager​ 继承自动挂载式的继承MonoBehaviour的单例模式基类

    1
    2
    3
    4
    public class MonoManager : SingletonAutoMono<MonoManager> 
    {
    private MonoManager() { }
    }
  2. 实现 Update​、FixedUpdate​、LateUpdate 生命周期函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Events;

    /// <summary>
    /// 公共Mono模块管理器
    /// </summary>
    public class MonoManager : SingletonAutoMono<MonoManager>
    {
    private MonoManager() { }

    private void Update() { }

    private void FixedUpdate() { }

    private void LateUpdate() { }
    }
  3. 声明对应事件或委托用于存储外部函数,并提供添加移除方法,从而达到让不继承 MonoBehaviour 的脚本可以执行帧更新或定时更新的目的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Events;

    /// <summary>
    /// 公共Mono模块管理器
    /// </summary>
    public class MonoManager : SingletonAutoMono<MonoManager>
    {
    private MonoManager() { }

    private event UnityAction updateEvent;
    private event UnityAction fixedUpdateEvent;
    private event UnityAction lateUpdateEvent;

    /// <summary>
    /// 将方法添加到公共帧更新Update方法内
    /// </summary>
    /// <param name="updateFunc">帧更新方法</param>
    public void AddUpdateListener(UnityAction updateFunc)
    {
    updateEvent += updateFunc;
    }

    /// <summary>
    /// 将方法从公共帧更新Update方法内移除
    /// </summary>
    /// <param name="updateFunc">要移除的帧更新方法</param>
    public void RemoveUpdateListener(UnityAction updateFunc)
    {
    updateEvent -= updateFunc;
    }

    /// <summary>
    /// 将方法添加到公共固定帧更新FixedUpdate方法内
    /// </summary>
    /// <param name="fixedUpdateFunc">固定帧更新方法</param>
    public void AddFixedUpdateListener(UnityAction fixedUpdateFunc)
    {
    fixedUpdateEvent += fixedUpdateFunc;
    }

    /// <summary>
    /// 将方法从公共固定帧更新FixedUpdate方法内移除
    /// </summary>
    /// <param name="fixedUpdateFunc">要移除的固定帧更新方法</param>
    public void RemoveFixedUpdateLinster(UnityAction fixedUpdateFunc)
    {
    fixedUpdateEvent -= fixedUpdateFunc;
    }

    /// <summary>
    /// 将方法添加到公共延迟帧更新LateUpdate方法内
    /// </summary>
    /// <param name="lateUpdateFunc">延迟帧更新方法</param>
    public void AddLateUpdateListener(UnityAction lateUpdateFunc)
    {
    lateUpdateEvent += lateUpdateFunc;
    }

    /// <summary>
    /// 将方法从公共延迟帧更新LateUpdate方法内移除
    /// </summary>
    /// <param name="lateUpdateFunc">要移除的延迟帧更新方法</param>
    public void RemoveLateUpdateListener(UnityAction lateUpdateFunc)
    {
    lateUpdateEvent -= lateUpdateFunc;
    }

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

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

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

  4. 声明协同程序开启关闭函数,从而达到让不继承 MonoBehaviour 的脚本可以执行协同程序的目的

    我们不需要自己声明协同程序开启关闭函数,可以直接使用来自基类 MonoBehaviour 的方法

使用方法

调用公共 Mono 模块的帧更新方法示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using UnityEngine;

public class TestL6Manager : BaseManager<TestL6Manager>
{
private TestL6Manager() { }

public void ICanUpdate()
{
MonoManager.Instance.AddUpdateListener(MyUpdate);
}

public void ICanStopUpdate()
{
MonoManager.Instance.RemoveUpdateListener(MyUpdate);
}

public void MyUpdate()
{
Debug.Log("Test6Mgr");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;
using UnityEngine;

public class Main : MonoBehaviour
{
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
TestL6Manager.Instance.ICanUpdate();

if (Input.GetKeyUp(KeyCode.Space))
TestL6Manager.Instance.ICanStopUpdate();
}
}

按下空格键就输出,抬起空格键就停止输出:

image

调用公共 Mono 模块的协程示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System.Collections;
using UnityEngine;

public class TestL6Manager : BaseManager<TestL6Manager>
{
private Coroutine testCoroutine;

private TestL6Manager() { }

private IEnumerator Test()
{
Debug.Log("协程启动");
yield return new WaitForSeconds(3f);
Debug.Log("TestTestTest");
}

public void StartTestCoroutine()
{
testCoroutine = MonoManager.Instance.StartCoroutine(Test());
}

public void StopTestCoroutine()
{
MonoManager.Instance.StopCoroutine(testCoroutine);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;
using UnityEngine;

public class Main : MonoBehaviour
{
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
TestL6Manager.Instance.StartTestCoroutine();

if (Input.GetKeyUp(KeyCode.Space))
TestL6Manager.Instance.StopTestCoroutine();
}
}

按下空格后以及按住空格3秒后的输出:

image