有了基类之后,我们便可以开始做可以移动的单位了,先来看看Enemy(这回将在文章中涉及到一些脚本以外的部分,然而好多东西我都忘了…… 所以还特地翻出来视频重新看了一眼)。
需要涉及到的部分有:
- 创建动画和控制器
- 添加刚体、碰撞体等属性
- 添加脚本
一. 创建动画和控制器
在本例中涉及到的动画均为帧动画,所以在创建前我们需要准备的东西就是一个符合unity要求格式的“图片合集”。
需要的就是这两个文件,本质上来说其实就是一张由多个小图合成的大图以及他们对应的描述信息(太长不截取了,有兴趣的可以用记事本自己打开看看)。获取这个资源的方式有很多,比如TexturePacker就可以导出为Unity的格式。
当制作好的资源被导入Unity后,在资源浏览器上便可以把他们当做独立的图片去进行处理。
制作动画的方法很简单,在这里选取你所需要的图片后,直接拖拽到你所需要创建动画的物体上(比如一个事先建好的空的GameObject),Unity便会自动为你生成一个动画并提示你保存。值得注意的是,如果你的这个物体从未添加过“动画控制器(AnimatorController)”的话,则Unity会同时帮助你创建一个控制器。控制器的作用便是“控制在何时应播放哪一段动画”。创建好的控制器可以在Inspector(检视器)视图中找到。
当所有的动画都创建好之后,我们双击对应的动画控制器,将会看到其中有类似这样的一些东西:
通过在这个界面进行编辑,便可以很简单的控制动画的播放。黄色和灰色的矩形指的是我们创建的动画,而其他颜色的则是一些状态。黄色在这里指的是默认播放的动画,而那些箭头则是动画之间的切换关系。
切换动画使用的方法便是一些标记值,在unity5里面一共包括四种:Float、Int、Bool、Trigger。
在这里面Trigger可以理解为也是一个Bool值,平常是false,被触发之后会变成True并且执行切换的工作之后立马再变回false。动画之间的切换关系(也就是那些箭头)的任务就是去根据你所设定的条件进行判断。
由于我们的敌人有两种,但是他们的行为是相同的,不同的只有部分数值和他们的显示图片,所以在这里我们还会用到一个叫AnimatorOverrideController的东西,它的作用就是把一个已有控制器的某些信息替换(比如动画中的图片),其余的东西(比如切换关系)依旧保留原本的设定,这样便于将类似行为的物体分类管理。
具体更详细的信息,以后也许会单独写成一篇文章,在这里就不详细说明了。
二. 添加刚体、碰撞体等属性
对于我们的移动单位来说,为了能够正确的触发一些事件以及之前我们使用了Linecast方法来判断碰撞,所以我们需要为它们创建自己的碰撞体和刚体。
需要注意的是,在刚体(Rigidbody 2D)属性中,我们勾选了Is Kinematic选项。在这种情况下,物体将不会受到物理引擎的限制,所有的参数都由脚本手动设定。在我们的例子中,我们不希望游戏一开始所有任务都掉到了画面底端(重力),也不希望我们的物体被触碰之后就弹开或者旋转,所以我们勾选了这一项。
三. 添加脚本
依旧先看一下代码的基本结构:
注意这里面继承的不再是一般的MonoBehiever而是之前做好的MovingObject类。
在我们重写的Start()方法中:
我们把每一个敌方单位都加入了GameManager所持有的数组中;获得了动画器(Animator)的引用;最后把移动目标设定为了玩家。
同时我们也重写了AttemptMove <T>() 方法:
通过这种方法,我们便可以使得敌方单位每两回合再尝试一次移动,以免难度过高(→_→)
MoveEnemy()方法是由GameManager调用的,用来规定敌方单位的移动方式:
可以看到在这里,我们规定的移动方式是“优先处理x方向上的差距,向玩家方向移动;若x方向处于同一位置则移动y方向的坐标”。
需要注意的是这里使用了Mathf类里的Abs()方法,熟悉程序的人应该一眼就能看出,这个方法的作用是对一个数取绝对值,那么为什么不直接判断targrt.position.x == transform.position.x而是要和后面的那个float.Epsilon做差呢?这是由于在Unity中的position属性中的数值都是由float类型进行标记的,因此在计算过程中有可能出现精度问题导致的误差。在这里float.epsilon是一个非常非常小的值(1.401298 e-45)因此如果两个数的差值小于这个数,我们便认为这两个数相等,借此解决由精度不够造成的一些计算误差。
最后,由于我们集成了MovingObject类,所以我们自然需要实现OnCantMove <T>() 这个方法(接口):
那么在这里我们只需要处理和Player碰撞时发生的事件:
- 触发animator中的“EnemyAttack”触发器,这样便会使得敌方单位的动画变成攻击的状态;
- 随机播放攻击的音效;
- 执行Player中的LoseFood方法,这样将会使玩家受到的攻击造成实际的效果。
就这么多吧…… 下一篇文章将把Player中与Enemy的区别列举并解释出来。