目前枪械系统的功能列表如下

  • 开枪
    • 底层系统层
    • 表现层
  • 填弹
    • 底层系统层
    • 表现层
  • 换枪
    • 底层系统层
    • 表现层
  • 捡枪
    • 底层系统层
    • 表现层
  • 弹药补给
    • 底层系统层
    • 表现层
  • 补给站补给
    • 底层系统层
    • 表现层

捡枪的功能实现图如下

捡枪实现

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)//实现PickGun
{
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));
}
}

//...

}
}