我们看下枪械系统要做的功能列表
以上的功能列表还可以进一步拆分为如下
我们先看一下填弹的功能实现图

按键填弹实现
我们先实现按下R键,发送ReloadCommand
来填弹
我们在Command文件夹里新建ReloadCommand
文件
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
| using FrameWorkDesign;
namespace ShootingEditor2D { public class ReloadCommand : AbstractCommand { protected override void OnExecute() { var currentGun = this.GetSystem<IGunSystem>().CurrentGun; var gunConfigItem = this.GetModel<IGunConfigModel>().GetItemByName(currentGun.Name.Value); var needBulletCount = gunConfigItem.BulletMaxCount - currentGun.AmmoNumInGun.Value;
if (needBulletCount > 0) {
currentGun.State.Value = GunState.Reload;
this.GetSystem<ITimeSystem>().AddTaskDelay(gunConfigItem.ReloadSeconds, () => { if (currentGun.BulletCountOutGun.Value > 0) { if (currentGun.BulletCountOutGun.Value >= needBulletCount) { currentGun.AmmoNumInGun.Value += needBulletCount; currentGun.BulletCountOutGun.Value -= needBulletCount; } else { currentGun.AmmoNumInGun.Value += currentGun.BulletCountOutGun.Value; currentGun.BulletCountOutGun.Value = 0; } } currentGun.State.Value = GunState.Idle; }); } } } }
|
接下来,我们修改Gun
脚本,为它添加Reload
方法
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
| using UnityEngine; using FrameWorkDesign;
namespace ShootingEditor2D { public class Gun : MonoBehaviour,IController { private Bullet m_Bullet;
private GunInfo m_GunInfo;
private int mMaxBulletCount;
private void Awake() { m_Bullet = transform.Find("Bullet").GetComponent<Bullet>();
m_GunInfo = this.GetSystem<IGunSystem>().CurrentGun;
mMaxBulletCount = this.SendQuery(new MaxBulletCountQuery(m_GunInfo.Name.Value)); }
public void Reload() { if (m_GunInfo.State.Value == GunState.Idle && m_GunInfo.AmmoNumInGun.Value != mMaxBulletCount && m_GunInfo.BulletCountOutGun.Value > 0) { this.SendCommand<ReloadCommand>(); } } } }
|
修改Player
脚本,添加R键的监听
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
| using UnityEngine;
namespace ShootingEditor2D { public class Player : MonoBehaviour {
private void Update() { if(Input.GetButtonDown("Jump")) m_JumpPressed = true; if (Input.GetKeyDown(KeyCode.J)) { m_Gun.Shoot(); } if (Input.GetKeyDown(KeyCode.R)) { m_Gun.Reload(); } }
} }
|
注意这里的编程实践,我们把大部分的按键监听都放在了Palyer
脚本里,避免在其他脚本中(比如Gun
脚本)调用Update
生命周期函数(来监听按键等)。
自动填弹实现
我们直接按照功能实现图里设计的,在ShootCommand
里面能够进行子弹判断并发送ReloadCommand
,我们在每次子弹射击完之后加一个判断
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
| using FrameWorkDesign;
namespace ShootingEditor2D { public class ShootCommand : AbstractCommand { public static readonly ShootCommand Instance = new ShootCommand(); protected override void OnExecute() { var gunSystem = this.GetSystem<IGunSystem>(); gunSystem.CurrentGun.AmmoNumInGun.Value--; gunSystem.CurrentGun.State.Value = GunState.Shooting;
var gunConfigItem = this.GetModel<IGunConfigModel>().GetItemByName(gunSystem.CurrentGun.Name.Value); var timeSystem = this.GetSystem<ITimeSystem>(); timeSystem.AddTaskDelay( 1/gunConfigItem.Frequency, () => { gunSystem.CurrentGun.State.Value = GunState.Idle;
if (gunSystem.CurrentGun.AmmoNumInGun.Value == 0 && gunSystem.CurrentGun.BulletCountOutGun.Value > 0) { this.SendCommand<ReloadCommand>(); } }); } } }
|
Command
嵌套复用和Query
的嵌套复用是此框架的特色之一,要留意