枪械系统实现
因为游戏设计时就有枪械切换的功能,这就需要设计枪械系统。通过枪械系统可以查询当前主角使用的是哪把枪,以及这把枪有多少枚子弹。

先创建一个GunInfo
,用于记录某类枪子弹数量,未来可以增加枪械名字,类型等信息。
在System文件夹中新建一个GunSystem文件夹,在其中新建GunInfo
1 2 3 4 5 6 7 8 9
| using FrameWorkDesign;
namespace ShootingEditor2D { public class GunInfo { public BindableProperty<int> AmmoNum; } }
|
也是在GunSystem文件夹内,新建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
| using FrameWorkDesign;
namespace ShootingEditor2D { interface IGunSystem : ISystem { GunInfo CurrentGun { get; } }
public class GunSystem : AbstractSystem, IGunSystem { public GunInfo CurrentGun { get; } = new GunInfo() { AmmoNum = new BindableProperty<int>() { Value = 3 } };
protected override void OnInit() { } } }
|
接着在ShootingEditor2D
注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| using FrameWorkDesign;
namespace ShootingEditor2D { public class ShootingEditor2D : Architecture<ShootingEditor2D> { protected override void Init() { this.RegisterSystem<IStatSystem>(new StatSystem()); this.RegisterSystem<IGunSystem>(new GunSystem());
this.RegisterModel<IPlayerModel>(new PlayerModel()); } } }
|
添加开枪命令
在Command文件夹中新建ShootCommand
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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.AmmoNum.Value--; } } }
|
因为游戏中的开枪命令属于频繁触发的命令,所以为了GC这里声明了一个单例引用。同理使用对象池也可以
注意如果对命令系统做了记录(类似于软件中的Ctrl+Z历史记录),不可以使用单例或对象池
修改Gun
脚本
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
| using UnityEngine; using FrameWorkDesign;
namespace ShootingEditor2D { public class Gun : MonoBehaviour,IController { private Bullet m_Bullet;
private GunInfo m_GunInfo;
private void Awake() { m_Bullet = transform.Find("Bullet").GetComponent<Bullet>();
m_GunInfo = this.GetSystem<IGunSystem>().CurrentGun; }
public void Shoot() {
if (m_GunInfo.AmmoNum.Value > 0) { var bullet = Instantiate(m_Bullet, m_Bullet.transform.position, m_Bullet.transform.rotation); bullet.transform.localScale = m_Bullet.transform.lossyScale;
bullet.gameObject.SetActive(true);
this.SendCommand(ShootCommand.Instance); } }
private void OnDestroy() { m_GunInfo = null; }
public IArchitecture GetArchitecture() { return ShootingEditor2D.Interface; } } }
|
完成UI
修改UIController
脚本,顺便将框架的引用在OnDestroy里面置空
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
| using UnityEngine; using FrameWorkDesign; using System;
namespace ShootingEditor2D { public class UIController : MonoBehaviour,IController { private IGunSystem m_GunSystem;
private void Awake() { m_GunSystem = this.GetSystem<IGunSystem>(); }
private void OnDestroy() { m_StatSystem = null; m_PlayerModel = null; m_GunSystem = null; }
private void OnGUI() { GUI.Label(new Rect(10, 60, 300, 100), $"子弹:{m_GunSystem.CurrentGun.AmmoNum.Value}",m_LableStyle.Value); } } }
|
一定不要忘了在Controller层引用框架的其他层级时在OnDestroy里面置空,因为框架的代码是依赖C#本身GC的,而不是Unity的GC,不置空会在内存内长时间保留。