目前枪械系统的功能列表如下
捡枪的功能实现图如下

IGunSystem
需要支持枪械的数据能够缓存起来,这个缓存机制在未来还要支持切换枪的功能。
我们使用Queue(先入先出)来缓存枪械,不过只能单向切枪。数据结构的选取需要考虑数据是否不断变化和数据是否频繁查询。
修改IGunSystem
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| using FrameWorkDesign; using System.Collections.Generic; using System.Linq;
namespace ShootingEditor2D { interface IGunSystem : ISystem { GunInfo CurrentGun { get; } void PickGun(string name, int ammoNumInGun, int bulletCountOutGun); }
public class OnCurrrentGunChanged { public string Name { get; set; } }
public class GunSystem : AbstractSystem, IGunSystem {
private Queue<GunInfo> mGunInfos = new Queue<GunInfo>(); public void PickGun(string name, int ammoNumInGun, int bulletCountOutGun) { if (CurrentGun.Name.Value == name) { CurrentGun.BulletCountOutGun.Value += ammoNumInGun; CurrentGun.BulletCountOutGun.Value += bulletCountOutGun; } else if (mGunInfos.Any(gunInfo => gunInfo.Name.Value == name)) { var gunInfo = mGunInfos.First(gunInfo => gunInfo.Name.Value == name); gunInfo.BulletCountOutGun.Value += ammoNumInGun; gunInfo.BulletCountOutGun.Value += bulletCountOutGun; } else { var currentGunInfo = new GunInfo() { AmmoNumInGun = new BindableProperty<int>() { Value = CurrentGun.AmmoNumInGun.Value }, BulletCountOutGun = new BindableProperty<int>() { Value = CurrentGun.BulletCountOutGun.Value }, Name = new BindableProperty<string>() { Value = CurrentGun.Name.Value }, State = new BindableProperty<GunState>() { Value = GunState.Idle } };
mGunInfos.Enqueue(currentGunInfo);
CurrentGun.Name.Value = name; CurrentGun.AmmoNumInGun.Value = ammoNumInGun; CurrentGun.BulletCountOutGun.Value = bulletCountOutGun;
this.SendEvent(new OnCurrrentGunChanged() { Name = name }); } }
} }
|
添加PickGunCommand
在Command文件夹里面新建PickGunCommand
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| using FrameWorkDesign;
namespace ShootingEditor2D { public class PickGunCommand : AbstractCommand { private readonly string mName; private readonly int mAmmoNumInGun; private readonly int mBulletCountOutGun;
public PickGunCommand(string name, int ammoNumInGun, int bulletCountOutGun) { mName = name; mAmmoNumInGun = ammoNumInGun; mBulletCountOutGun = bulletCountOutGun; }
protected override void OnExecute() { this.GetSystem<IGunSystem>() .PickGun(mName,mAmmoNumInGun,mBulletCountOutGun); } } }
|
测试
我们可以修改Player
脚本来测试一下目前的代码
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
| using UnityEngine; using FrameWorkDesign;
namespace ShootingEditor2D { public class Player : MonoBehaviour,IController {
private void Update() { if (Input.GetKeyDown(KeyCode.P)) { this.SendCommand(new PickGunCommand("冲锋枪", 30, 100)); } }
public IArchitecture GetArchitecture() { return ShootingEditor2D.Interface; } } }
|
打开游戏按下P键,可以发现换枪成功,但是有一些UI没有更新
修改UIController
为了解决UI问题,我们直接在Awake方法里面添加监听。我们的MaxBulletCountQuery
引用的是GunConfigModel
里面的地址,而当CurrentGun
改变时此地址在内存的位置不会改变,依然显示的是之前的枪的MaxBulletCount,所以我们需要再进行一次查询来更新内存地址
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 UnityEngine; using FrameWorkDesign; using System;
namespace ShootingEditor2D { public class UIController : MonoBehaviour,IController {
private int m_MaxBulletCount;
private void Awake() {
m_MaxBulletCount = this.SendQuery(new MaxBulletCountQuery(m_GunSystem.CurrentGun.Name.Value));
this.RegisterEvent<OnCurrrentGunChanged>(e => { m_MaxBulletCount = this.SendQuery(new MaxBulletCountQuery(e.Name)); }).UnregisterWhenGameObjectDestroyed(gameObject); }
} }
|
创建捡枪脚本
我们现在场景中创建一个2D Object——Sprites——Circle,命名为GunPickItem,给它挂载Circle Collider 2D,并勾选is Trigger。
在Scripts——ViewController——Gameplay文件夹内新建GunPickItem
脚本,并把这个脚本挂载在GunPickItem上
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
| using UnityEngine; using FrameWorkDesign;
namespace ShootingEditor2D { public class GunPickItem : MonoBehaviour,IController { public string gunName = "手枪"; public int ammoNumInGun = 1; public int bulletCountOutGun = 1;
public IArchitecture GetArchitecture() { return ShootingEditor2D.Interface; }
private void OnTriggerEnter2D(Collider2D collision) { if (collision.CompareTag("Player")) { this.SendCommand(new PickGunCommand(gunName,ammoNumInGun,bulletCountOutGun)); Destroy(gameObject); } } } }
|
将Player
脚本里用于测试的代码删掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| using UnityEngine; using FrameWorkDesign;
namespace ShootingEditor2D { public class Player : MonoBehaviour,IController {
private void Update() { if (Input.GetKeyDown(KeyCode.P)) { this.SendCommand(new PickGunCommand("冲锋枪", 30, 100)); } }
} }
|