常规方法:通过委托联系宝石与门(观察者模式)
流程是:
- 在宝石脚本中创建委托,并在碰撞函数中调用(Invoke());
- 在门脚本中创建函数(Open())摧毁对象,并且订阅宝石中的委托。
- 当宝石碰撞,调用了委托,订阅委托的两个门就执行相应动作(摧毁)。
这个方法缺点是门与宝石耦合
给宝石添加委托
event关键字:其他类不可使用=,只可以+=或-=
碰撞事件函数中调用委托
给门添加Gate脚本
写一个函数来销毁门
void Open() { Destroy(gameObject); }
|
获取gateTrigger实例并且
在**Onenable()**中订阅Open函数
引入Scriptable Object实现解耦
新建一个EventChannels文件夹并且创建VoidEventChannel脚本
将它继承于ScriptableObject,实现声明委托、调用、订阅、退订等操作。
using UnityEngine; [CreateAssetMenu(menuName = "Data/EventChannels/VoidEventChannel", fileName = "VoidEventChannel_")] public class VoidEventChannel : ScriptableObject { event System.Action Delegate; public void Broadcast() { Delegate?.Invoke(); } public void AddListener(System.Action action) { Delegate += action; } public void RemoveListener(System.Action action) { Delegate -= action; } }
|
在中Data文件夹中创建EventChannels文件夹,并创建VoidEventChannel_文件
门开关之类的命名为VoidEventChannel_GateTriggered
修改GateTrigger代码
序列化获取VoidEventChannel可脚本化对象,注释定义委托代码,在触发器中调用VoidEventChannel中的调用委托函数。
using UnityEngine; public class GateTrigger : MonoBehaviour { [SerializeField] AudioClip pickUpSound; [SerializeField] ParticleSystem pickUpVFX; [SerializeField] VoidEventChannel gateTriggeredEventChannel;
private void OnTriggerEnter(Collider other) { gateTriggeredEventChannel.Broadcast();
SoundEffectsPlayer.audioSource.PlayOneShot(pickUpSound); Instantiate(pickUpVFX, transform.position, Quaternion.identity); Destroy(gameObject); } }
|
修改Gate代码
序列化获取VoidEventChannel可脚本化对象,调用其中订阅和退订函数,意为委托执行时摧毁门。
using UnityEngine; public class Gate : MonoBehaviour { [SerializeField] VoidEventChannel gateTriggeredEventChannel; private void OnEnable() { gateTriggeredEventChannel.AddListener(Open); } private void OnDisable() { gateTriggeredEventChannel.RemoveListener(Open); } void Open() { Destroy(gameObject); } }
|
配置
GateTrigger和相对应的Gate拖入可视化脚本对象,VoidEventChannel
此时,拾取蓝宝石将会摧毁宝石和红门。