抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

常规方法:通过委托联系宝石与门(观察者模式)

流程是:

  • 在宝石脚本中创建委托,并在碰撞函数中调用(Invoke());
  • 在门脚本中创建函数(Open())摧毁对象,并且订阅宝石中的委托。
  • 当宝石碰撞,调用了委托,订阅委托的两个门就执行相应动作(摧毁)。

image-20220921125104646

这个方法缺点是门与宝石耦合

给宝石添加委托

event关键字:其他类不可使用=,只可以+=或-=

image-20220921124328815

碰撞事件函数中调用委托

image-20220921124431032

给门添加Gate脚本

写一个函数来销毁门

void Open()
{
Destroy(gameObject);
}

获取gateTrigger实例并且

在**Onenable()**中订阅Open函数

image-20220921125021772

引入Scriptable Object实现解耦

image-20220921134702232

新建一个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();//调用委托
// 等价于如下代码
// if (Delegate!=null)
// {
// Delegate.Invoke();
// }
}
public void AddListener(System.Action action) { Delegate += action; }//订阅
public void RemoveListener(System.Action action) { Delegate -= action; }//退订
}

在中Data文件夹中创建EventChannels文件夹,并创建VoidEventChannel_文件

image-20220921150235366

门开关之类的命名为VoidEventChannel_GateTriggered

修改GateTrigger代码

序列化获取VoidEventChannel可脚本化对象,注释定义委托代码,在触发器中调用VoidEventChannel中的调用委托函数。

using UnityEngine;
public class GateTrigger : MonoBehaviour
{
[SerializeField] AudioClip pickUpSound;//音效
[SerializeField] ParticleSystem pickUpVFX;//特效
[SerializeField] VoidEventChannel gateTriggeredEventChannel;

// public event System.Action OpenDoor;//定义委托
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()
{
//gateTrigger.OpenDoor += Open;
gateTriggeredEventChannel.AddListener(Open);
}
private void OnDisable()
{
//gateTrigger.OpenDoor -= Open;
gateTriggeredEventChannel.RemoveListener(Open);
}
void Open()
{
Destroy(gameObject);
}
}

配置

GateTrigger和相对应的Gate拖入可视化脚本对象,VoidEventChannel

image-20220921165250298

image-20220921165627060

此时,拾取蓝宝石将会摧毁宝石和红门。

评论