之前写了一篇介绍事件和委托的帖子,但是没怎么运用过,只是使用一些简单的事件
这次看了一个项目的源码,趁着这个机会好好研究一下事件和委托的作用
event的作用
1 2
| public Action Action_A; public event Action Action_B;
|
Action:安全性较差,外部代码可以触发这个委托(使用.Invoke())
event Action:安全性强,外部只能订阅或取消订阅(使用-=或+=),不能直接触发事件
使用情景
假设现在有两个类ClassA、ClassB,在以下情况推荐使用事件委托来实现
- 需要在特定的时机触发某个方法
- 需要使用其他实例的私有属性
- 某个方法的实现有两种限制,比如UI中需要该物体处于激活状态,且按下手柄的A键
前面两个都还比较好理解,第三种情况除了事件本身Invoke()调用的时机外,还可以通过注册(+=)和注销(-=)来控制这个事件中是否有任务来控制释放的时机
需要在特定时机时触发某个方法
场景:
ClassA需要特定的时候(比如参数intA等于0、或某个按钮被按下)执行方法FuncA
具体操作:
- 创建一个事件
ActionA
- 初始化的时候注册这个事件
ActionA += FuncA
- 当
intA等于0时触发这个事件ActionA.Invoke()
示例代码:
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
| public class ClassA : MonoBehaviour { public int intA; private Action ActionA;
private void Start() { ActionA += FuncA; UpdateNumber().Forget(); }
private async UniTask UpdateNumber() { while (true) { await UniTask.Delay(TimeSpan.FromSeconds(.5f), ignoreTimeScale: false); intA = (int)Mathf.Repeat(--intA, 11);
if (intA == 0) ActionA?.Invoke(); } }
private void FuncA() { Debug.Log($"当前值为: {intA}"); } }
|
需要使用其他实例的私有属性
场景:
ClassA需要特定的时候(比如参数intA等于0、或某个按钮被按下)获取其他类中的私有方法FuncB或参数strB
具体操作:
ClassA创建一个事件ActionA
在ClassB中注册这个事件ClassA.ActionA += FuncB
当intA等于0时ActionA.Invoke()
示例代码:
当ClassA中的intA等于0时,就会执行ClassB中的FuncB了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class ClassA : MonoBehaviour { public int intA; public Action ActionA;
private void Start() { UpdateNumber().Forget(); }
private async UniTask UpdateNumber() { while (true) { await UniTask.Delay(TimeSpan.FromSeconds(.5f), ignoreTimeScale: false); intA = (int)Mathf.Repeat(--intA, 11); if (intA == 0) ActionA?.Invoke(); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class ClassB : MonoBehaviour { private string strB = "I am private"; public ClassA A;
private void Start() { A.ActionA += FuncB; }
private void FuncB() { Debug.Log(strB); } }
|
某个方法的实现有两种限制
场景:
ClassA需要特定的时候(比如参数intA等于0、某个按钮被按下),且B处于激活状态时执行方法FuncA
具体操作:
ClassA创建事件ActionA
- 在激活
B时将FuncA注册给ActionA,停用B时将FuncA注销掉
示例代码:
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
| public class ClassA : MonoBehaviour { public int intA; public Action ActionA;
private void Start() { UpdateNumber().Forget(); }
private async UniTask UpdateNumber() { while (true) { await UniTask.Delay(TimeSpan.FromSeconds(.5f), ignoreTimeScale: false); intA = (int)Mathf.Repeat(--intA, 11);
if (intA == 0) ActionA?.Invoke(); } }
public void FuncA() { Debug.Log("我只有在intA等于0且B处于激活状态的时候执行"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class ClassB : MonoBehaviour { public ClassA A;
private void OnEnable() { A.ActionA += A.FuncA; }
private void OnDisable() { A.ActionA -= A.FuncA; } }
|