Unity框架之公共Mono模块

注:25年2月24日进行补充
这篇文章介绍一下公共Mono模块。

为什么有公共Mono模块?

很多时候我们写代码,不想继承MonoBehaviour类(比如减少性能开销、简化代码量,MonoBehaviour),但又想用MonoBehaviour里Update、Start等方法。这时候就需要搭建公共Mono模块来实现我们的需求了。

思路

以实现Update为例,既然我们知道,不继承MonoBehaviour类的不能直接调用Update等方法,那么有没有什么办法、把我们的方法塞到update里呢?
答案是有的,这里有个知识点是“委托和事件”,我们可以把我们的方法、塞到委托里,在继承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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using UnityEngine.Events;

public class MonoController : MonoBehaviour
{
//我创建两个事件,目的是提高安全性
private event UnityAction UnityStart;
private event UnityAction UnityUpdate;
//调用委托
private void Start()
{
if(UnityStart != null)
UnityStart();
}

private void Update()
{
if(UnityUpdate != null)
UnityUpdate();
}

//开始写我们的函数
public void AddStart(UnityAction action)
{
UnityStart += action;
UnityStart.invoke()//因为我们想添加后立即执行,Unity默认只执行一次
}

public void AddUpdate(UnityAction action)
{
UnityUpdate += action;
}
public void RemoveStart(UnityAction action)
{
UnityStart -= action;
}

public void RemoveUpdate(UnityAction action)
{
UnityUpdate -= action;
}
}

以上就是我们写的一个Mono控制器,接下来我们还需要写一个Mono管理器,既然是管理器我们肯定要继承单例模式基类脚本。管理器接收命令、分发到控制器执行。于是我创建个MonoMgr.cs的脚本:

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
using UnityEngine.Events;

public class MonoMgr : SingletonBase<MonoMgr>
{
//私有化一个控制器,写构造函数
private MonoController controller;
public MonoMgr()
{
GameObject obj = new GameObject("MonoController");
controller = obj.AddComponent<MonoController>();
}
//书写函数,我们加入的委托会在控制器执行
public void AddStart(UnityAction action)
{
controller.AddStart(action);
}

public void AddUpdate(UnityAction action)
{
controller.AddUpdate(action);
}
public void RemoveStart(UnityAction action)
{
controller.RemoveStart(action);
}

public void RemoveUpdate(UnityAction action)
{
controller.RemoveUpdate(action);
}
}

接下来举个例子如何调用它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//我们没继承MonoBehaviour
public class Test1
{
public void Update()
{
Debug.Log("示例");
}
}

public class Test : MonoBehaviour
{
void Start()
{
Test1 t = new Test1;
MonoMgr.GetInstance().AddUpdate(t.Update);
//上面是一个单例里添加方法
}
}

于是我又把这两个脚本写成一个,感觉很简洁了。

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
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Events;

public class MonoManager : SingleMono<MonoManager>
{
//私有化一个控制器,写构造函数
public event UnityAction onStart;
public event UnityAction onUpdate;
public event UnityAction onLateUpdate;
public event UnityAction onFixedUpdate;
// Start is called before the first frame update
void Start()
{
onStart?.Invoke();
}

// Update is called once per frame
void Update()
{
onUpdate?.Invoke();
}

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

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

//方法
public void AddStart(UnityAction action)
{
onStart += action;
onStart.invoke()//因为我们想添加后立即执行,Unity默认只执行一次
}
public void AddUpdate(UnityAction action)
{
onUpdate += action;
}
public void AddLateUpdate(UnityAction action)
{
onLateUpdate += action;
}
public void AddFixedUpdate(UnityAction action)
{
onFixedUpdate += action;
}
//清空方法
public void RemoveStart(UnityAction action)
{
onStart -= action;
}
public void RemoveUpdate(UnityAction action)
{
onUpdate -= action;
}
public void RemoveFixedUpdate(UnityAction action)
{
onFixedUpdate -= action;
}
public void RemoveLateUpdate(UnityAction action)
{
onLateUpdate -= action;
}
}