Unity项目实战-订阅者发布者模式
实战订阅者发布者模式详解
下面实例是一个射击类游戏,玩家可以切换枪支,最初的设计如下
public class Player:MonoBehaviour
{
//......省略代码逻辑
//我们以及配置好了Scroll的输入,并配置了Scroll的输入事件,当玩家滚动鼠标滚轮时,会调用OnScroll方法,并在ChangeWeapon方法中切换枪支并传回当前枪支的值赋给 currentWeapon 保证在切换枪支时,currentWeapon 能够及时更新处理Player中其他枪支逻辑,例如射击,换弹。
private void OnScroll(InputAction.CallbackContext context)
{
float scrollValue=context.ReadValue<Vector2>().y;
string weaponState=scrollValue>0?"up":"down";
currentWeapon = weapon.ChangeWeapon(weaponState);
}
}
public class Weapon:MonoBehaviour
{
//......省略代码逻辑
public Gun ChangeWeapon(string weaponState)
{
//更换枪支冷却
if(weaponSwitchTimer>0)
{
return weapons[currentWeaponIndex];
}
//切换枪支
weapons[currentWeaponIndex].gameObject.SetActive(false);
if(weaponState=="up")
{
currentWeaponIndex=(currentWeaponIndex+1)%weapons.Count;
}
else if(weaponState=="down")
{
currentWeaponIndex=(currentWeaponIndex-1+weapons.Count)%weapons.Count;
}
weapons[currentWeaponIndex].gameObject.SetActive(true);
weaponSwitchTimer=weaponSwitchTime;
return weapons[currentWeaponIndex];
}
}
通过上述代码,我们实现了枪支的切换,并及时更新了当前枪支的值,保证了在切换枪支时,currentWeapon 能够及时更新处理Player中其他枪支逻辑,例如射击,换弹。
但我们不希望只在拨动鼠标滚轮时切换枪支,而是多种方法可以切换枪支,根据我们的需求,我们可以使用一种设计模式来实现。
1. 订阅者发布者模式概述
订阅者发布者模式(也称为观察者模式)是一种设计模式,允许对象订阅事件并在事件发生时得到通知。这种模式通常用于解耦事件的发布者和订阅者,使得它们可以独立变化。
1.1 主要角色
- 发布者(Publisher):负责发布事件。在本例中,
Weapon
充当发布者。 - 订阅者(Subscriber):负责接收事件通知。在本例中,
Player
是订阅者。
2. 代码实现分析
2.1 Player 脚本
public class Player : MonoBehaviour
{
private Gun currentWeapon;
private Weapon weapon;
void Awake()
{
weapon = GetComponent<Weapon>();
currentWeapon = weapon.GetCurrentWeapon();
weapon.OnWeaponSwicther += OnWeaponSwicther; // 订阅事件
}
private void OnWeaponSwicther(Gun newweapon)
{
currentWeapon = newweapon; // 更新当前武器
}
}
2.1.1 作用分析
- 订阅事件:
weapon.OnWeaponSwicther += OnWeaponSwicther;
这行代码将OnWeaponSwicther
方法订阅到OnWeaponSwicther
事件上。 - 事件处理:当
OnWeaponSwicther
事件被触发时,OnWeaponSwicther
方法被调用,更新当前武器。
2.2 Weapon 脚本
public class Weapon : MonoBehaviour
{
public delegate void OnWeaponSwicther(Gun newWeapon);
public event OnWeaponSwicther OnWeaponSwicther;
public void ChangeWeapen(string weapenState)
{
// 逻辑来改变武器
Gun newWeapon = ...; // 获取新的武器实例
OnWeaponSwicther?.Invoke(newWeapon); // 触发事件
}
}
2.2.1 作用分析
- 事件声明:
public event OnWeaponSwicther OnWeaponSwicther;
以OnWeaponSwicther
委托 声明了一个事件,允许其他对象订阅。 - 事件触发:
OnWeaponSwicther?.Invoke(newWeapon);
在武器切换时触发事件,通知所有订阅者。
2.3 在其他地方调用
当我们声明了事件后,我们可以在其他地方调用,不仅仅局限在鼠标输入,例如按键调用
public class UITest : MonoBehaviour
{
public Weapon weapon;
public Button button;
void Awake()
{
button.onClick.AddListener(WeaponTest);
}
void WeaponTest()
{
weapon.ChangeWeapen("up");
}
}
3. 设计的好处和可维护性
3.1 解耦
- 模块化:发布者和订阅者之间的解耦使得它们可以独立开发和修改。
- 灵活性:可以轻松添加或移除订阅者,而无需修改发布者的代码。
3.2 可维护性
- 易于扩展:可以在不改变现有代码的情况下添加新的订阅者。
- 清晰的事件流:通过事件机制,逻辑流更加清晰,易于理解和调试。
3.3 实际应用
- 动态更新:在游戏中,玩家可以动态切换武器,系统会自动更新当前武器的状态。
- 响应式设计:通过事件机制,系统可以对玩家的操作做出及时响应。
通过这种设计,游戏中的武器切换逻辑变得更加灵活和易于维护。订阅者发布者模式提供了一种优雅的方式来处理对象之间的通信,特别是在复杂的游戏系统中。