IGunConfigModel实现
这一节我们来实现在刚开始设计时提出的IGunConfigModel
枪械系统需求初步分析
我们在之前提到过,GunConfigModel是用来读取数据表的,里面是一些只读数据。我们在前几节写了GunInfo,GunInfo才是在运行时主要的枪械数据来源。
之前在设计GunInfo类的时候,已经设计了一个Name字段,这个Name字段就是用来查询配置相关数据的
所以我们需要让IGunConfigModel提供一个根据名字返回GunConfigItem的方法
IGunConfigModel在Scripts——Model文件夹内新建IGunConfigModel脚本
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364using System.Collections.Generic;using FrameWorkDesign;namespace ShootingEditor2D{ pub ...
枪械冷却功能实现
有了时间系统,我们就能让枪械发射后能返回默认状态了
修改ShootCommand
12345678910111213141516171819using FrameWorkDesign;namespace ShootingEditor2D{ public class ShootCommand : AbstractCommand { public static readonly ShootCommand Instance = new ShootCommand(); protected override void OnExecute() { //... var timeSystem = this.GetSystem<ITimeSystem>(); timeSystem.AddTaskDelay(0.33f, () => { gunSystem.CurrentGun. ...
时间系统
这一节我们来实现一个简单的时间系统
ITimeSystem时间系统肯定是在系统层的,它需要游戏一开始初始化时就能统计时间信息。
在Scripts——System文件夹下新建TimeSystem文件夹,并在其中新建ITimeSystem脚本
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107using System;using System.Collections.Generic;using UnityEngine;using FrameWorkDesign;namespace ShootingEditor2D{ interface ITimeSystem : ISystem { ...
开枪底层实现与枪械信息展示
IGunSystem初始值设定上一节我们实现好了GunInfo和GunState,接下来我们在IGunSystem里面给CurrentGun设置好初始值
12345678910111213141516171819202122232425262728293031323334353637using FrameWorkDesign;namespace ShootingEditor2D{ interface IGunSystem : ISystem { GunInfo CurrentGun { get; } } public class GunSystem : AbstractSystem, IGunSystem { public GunInfo CurrentGun { get; } = new GunInfo() { AmmoNumInGun = new BindableProperty<int> ...
GunInfo重构
从这一节开始,着手实践贫血模型和充血模型这两个概念,一上来就用纸上设计去实践充血模型非常困难,因为纸上设计需要有一定的抽象能力,而这个抽象能力的前提是大量的编码实践。所以我们先进行一些充血模型的编码实践。
首先看一下开枪功能实现图
功能实现图转化成代码的方法,有两种简单的方式:
从表现层开始写起。先实现界面布局,然后界面基本元素实现,然后再写一个Command(比如ShootCommand),再接着写Command对应的System,比如IGunSystem等,以此类推,就是按照:表现层——交互逻辑——数据/系统——表现逻辑 这样的顺序去实现功能。
从数据开始写起。先设计数据结构,再实现表现层的内容,这种方式的好处是一开始可能考虑得比较周全,程序结构不容易混乱,但是对设计者要求比较高,需要有一定得编码积累和设计经验。
第一种方式简单,符合常人思维,配合纸上设计,也能达到尽可能得周全。
GunInfo重构修改GunInfo
12345678910111213141516171819202122232425262728293031using FrameWorkDesig ...
贫血、充血模型实践说明
目前关于枪械系统的功能都已经实现好了
开枪
填弹
换枪
捡枪
弹药补给
补给站补给
总共6个功能,这6个功能对应6个命令
在第一季中,我们有说过命令在MVC中是为了分担Controller的交互逻辑部分的职责,交互逻辑在一般情况下操作数据,对数据进行增删改。
对数据进行变更之后,游戏或者App中的内部状态发生了改变,并对外发送状态变更事件,表现层就会更新视图表现。从接收事件到更新视图表现的这和个过程,就是MVC中的表现逻辑。
充血模型和贫血模型重点使用的地方就是在表现逻辑中。
现在枪械系统的六个功能基本上都是交互逻辑的范畴,也就是增删改数据(状态),这方面我们已经练习得够多了,接下来应该把重点放在查询上了。查询的部分其实就是帮助Controller分担表现逻辑职责,不然所有的查询逻辑都写到Controller层的话,那Controller层的代码量就会多很多。
使用充血模型,将Controller层的查询逻辑分离出来,这样交互逻辑用Command分离,查询逻辑用充血模型,代码更清晰。
我们的表现逻辑需要有
枪械、子弹的形象
枪械信息UI
换枪、捡枪、弹药补给功能图绘制
捡枪功能图绘制当Player捡到了一把枪,这个时候主角当前枪的数据应该马上替换成另一把枪的数据。而另一把枪应该包含GunInfo类里所有的数据
这是视频中的截图,bulletCountInGun对应AmmoNumInGun
换枪功能图绘制当捡到的特殊枪类的弹药用完之后,主角要换回默认的手枪。我们增加一个枪械切换功能,按下Q键会切换枪,这就需要我们把枪械数据缓存起来。
数据层设计+模块设计+命令+事件=游戏核心
表现层逻辑:加载、卸载(ResourceLoad、AssetBundle)
弹药补给功能图绘制我们为了方便,将补给的弹药量设为所有武器的弹药量,并不根据武器类型区分弹药。
弹药补给量根据弹夹子弹的数量来计算,比如冲锋枪弹夹中能装30发子弹,那么捡起一个弹药补给玩家就能增加30发冲锋枪弹药。
弹药补给站功能图绘制弹药补给站能够将所有枪的弹夹补满,功能图如下
开枪实现图与填弹实现图
在这一节中我们梳理枪械系统的各种功能需求,然后绘制枪械系统的功能实现图
名称
形象
子弹
弹夹容量
攻击力
频率
射程/范围
限制
换弹时间
描述
手枪
7
1
1发/秒
半屏
无限
3秒
默认枪
冲锋枪
30
1
6发/秒
2/3屏幕
需要弹药
3秒
无
步枪
50
3
3发/秒
1屏
需要弹药
1秒
有一定后坐力
狙击枪
12
6
1发/秒
1屏
需要弹药
5秒
红外瞄准+后坐力大
火箭筒
1
5
1发/秒
1屏
需要弹药
4秒
跟踪+爆炸
霰弹枪
1
1
1发/秒
半屏
需要弹药
1秒
一次发射6~12颗子弹
对于枪械系统,我们在表现层有两个地方需要展示枪械系统的数据,一个是UI界面,一个是角色形象
除了这两个比较明显的需求之外,还有一些隐性的功能需求,比如能不能开枪的判断,这个需要根据弹药量进行计算,再比如开枪之后发射什么样的子弹,具体怎么发射,子弹打中敌人怎么样没打中敌人怎么样,这些功能点都是枪械表现层的需求。
大致的需求如下:
界面 ...
枪械系统需求初步分析
v0.0.4版本规划枪械系统:
手枪
冲锋枪
步枪
狙击枪
火箭筒
霰弹枪
不同的枪配有不同的子弹,不同的子弹有不同的射击轨迹、范围、攻击力
主角能力:
二段跳
攀墙
冲刺
主角数值:
血量
弹药量
敌人:
生命值
开枪的远程敌人
掉落弹药补给、回血
关卡:
可破坏物
陷阱
机关
回血道具
最大生命+1
终点
起始点
补给站
对话系统:
角色设置剧情
系统:
存档系统
关卡编辑系统
对话系统
统计系统
成就系统
背包系统
主角的Model
v0.0.4版本内容有点多,而且都不是一个具体的可执行方案。
每一个设计任务都包含游戏设计、程序设计、程序编码三个步骤。因为游戏设计在这里不是重点,所以在接下来的游戏设计仅仅是为了演示框架的使用。
枪械系统
手枪
冲锋枪
步枪
狙击枪
火箭筒
霰弹枪
不同的枪配有不同的子弹,不同的子弹有不同的射击轨迹、范围、攻击力
详细设定表
名称
形象
子弹
弹夹容量
攻击力
频率
射程/范围
限制
换弹时间
描述
手枪
7
1
1发/秒
半屏
无限
3秒
默认枪
冲锋枪
30
1
6发/秒
2 ...
敌人AI、归档与v0.0.4规划
修改Enemy的Prefab双击Enemy的Prefab,进入Prefab的编辑界面,为了让AI行动,我们要添加一些检测点。
给Enemy对象添加子节点,分别命名为WallCheck、FallCheck、GroundCheck,让这些子节点全都挂载Circle Collider 2D和Trigger 2D Check。同时将Trigger 2D Check的Target Layer设为Default,将Circle Collider 2D的Trigger开启,Radius设为0.01.
将这三个子节点调整到合适的位置。
添加Enemy脚本在ViewController的GamePlay文件夹中添加Enemy脚本,并将此脚本挂载在Enemy的Prefab上,注意在Prefab模式下挂载
123456789101112131415161718192021222324252627282930313233343536373839using UnityEngine;namespace ShootingEditor2D{ public class Enemy : MonoBeha ...