在前面的教程(1)和(2)中,我们介绍了如何使用Unity创建《吃豆人》的迷宫,以及添加吃豆人的动画。今天的文章将介绍如何设置吃豆人物理以及添加豆豆。

吃豆人物理

现在吃豆人也只是一张没有物理特性的图片,所以它不会移动。在吃豆人上新加一个Collider使其具有物理性质,然后周围的物体就可以与它进行碰撞而非直接穿过。
吃豆人可以到处移动。Rigidbody可用于处理重力、速度和其它推动它移动的力。物理世界所有可以移动的物体都需要一个Rigidbody组件。
在层次面板中选中pacman,依次点击Add Component->Physics 2D->Circle Collider 2D添加碰撞器,同样依次点击Add Component->Physics 2D->Rigidbody 2D添加Rigidbody。使用下图的设置:

1.png

现在吃豆人可以与周围的物体进行碰撞了。这也会导致所有绑定到pacman的脚本中的OnCollisionEnter2D函数被调用。

Movement脚本

现在有几种让吃豆人移动的方法。最简单的就是创建脚本,并检测键盘方向键操作,然后按照对应的方向移动吃豆人。但这种操作不好。我们来试试复杂点的办法。玩家按下某个方向键时,吃豆人都在相应方向移动一个完整单位。豆豆也会按照一个单位的间隔距离来摆放,所以吃豆人每次需要移动一个完整单位。在层次面板中选中pacman,依次点击Add Component->New Script新建C#脚本PacmanMove。将脚本放在项目视图中新建的Scripts文件夹下:

2.png

双击脚本会看到如下代码:

游戏启动时Unity会自动调用Start函数。Update函数会不停调用,几乎都是每秒60次(基于当前帧率,场景中东西过多可能会有所下降)。还有另一种更新函数叫FixedUpdate。也会不停调用,但时间周期固定。Unity以固定的时间周期来进行物理计算,所以物理相关的内容最好使用FixedUpdate:

我们需要一个公共变量以便后面在检视面板中修改移动速度:

还需要一个方法来判断吃豆人是否可以朝某个方向前进,或者前面是否有墙。例如,如果想知道前面是否有墙,就从吃豆人前方一单位距离处发出射线到吃豆人,看看是否撞到东西。如果撞到的是吃豆人自身则什么都没有,否则就是有墙。函数如下:

注:这里只是简单的从距离吃豆人一单位的点 (pos + dir)发射到吃豆人自身(pos)。
还要一个函数让吃豆人朝给定方向移动一单位的距离。只需:
transform.position += dir;
但这看起来太生硬了,因为一步很大。我们想让它更平滑的移动,每次一小步。将目的地保存到变量,然后在FixedUpdate函数中一步步移动:

注:使用GetComponent获取pacman的Rigidbody组件用于移动(永远不要用transform.position来移动带有Rigidbody的游戏对象)。
在不移动的时候要注意按下的方向键。注:当前位置就是目的地时不会移动。
在FixedUpdate函数中加入输入控制:

注:将transform.position转换为Vector2是与其它Vector2比较或相加的唯一方法。-Vector2.up表示left, -Vector2.right表示down。保存脚本后点击Play可以看到按下方向键后吃豆人会移动:

3.gif

设置动画参数

现在吃豆人可以在迷宫中四处移动来,但移动的动画不太对。没关系,只需简单的计算移动方向并设置动画参数即可:

注:这里使用基本的向量数学来计算移动方向。只需将目标位置与当前位置相减即可

到此吃豆人的移动就完成了。保存脚本后点击Play可以看到移动动画也正常了:

4.gif

保证吃豆人在最上层

在制作豆豆之前,要先保证吃豆人在所有物体上层。这是2D游戏,所以这里没有3d游戏中的Z值。也就是说Unity按照它自己的想法来绘制物体。我们要确保吃豆人绘制值所有物体上层。
有两种办法。改变Sprite Renderer的Sorting Layer 属性,或改变Order in Layer 属性。对于有很多对象的游戏来说使用Sorting Layer 更合适,这里我们只要将Order in Layer 改为1就好:

5.png

注:Unity会按从低到高的顺序来绘制对象。所以将吃豆人的Order in Layer设为1后,Unity会先绘制Order为0的迷宫、豆豆等。这样吃豆人就可以永远在最上层。

豆豆

吃豆人吃的就是豆豆。就像现在的水果和食物。首先制作一张2x2像素的图作为豆豆。将图片保存到Assets/Sprites 文件夹下,并使用如下导入设置:

6.png

然后将它拖拽到场景。我们希望在吃豆人走过豆豆时收到通知,所以在检视面板中依次点击 Add Component->Physics 2D->Box Collider 2D并选中Is Trigger:

7.png

注:启用IsTrigger的Collider只会接收碰撞信息,不与其它物体进行物理碰撞。
不论何时在吃豆人或怪物走过豆豆时Unity都会自动调用OnTriggerEnter2D函数。依次点击Add Component->New Script新建C#脚本Pacdot,并将其放到Scripts文件夹下:

这里不需要Start或Update函数,只需上面提到的OnTriggerEnter2D函数:

这个函数很简单。就是检测是否有物体走过,如果有就销毁豆豆:

注:如果想在此游戏中获得高分,就要多吃些豆豆。注层次面板中右击Pac-Dot,选中Duplicate并移动到其它空位。注意豆豆的位置都是类似(1, 2) 而不能是(1.003, 2.05)这样。
重复添加豆豆并摆放后结果如下:

8.png

点击Play会看到吃豆人可以吃豆豆了:

9.gif

也可将所有的豆豆都放在迷宫下面:

10.png

这样将迷宫折叠后层次面板看起来就比较简洁:

11.png

在下篇最终教程(4)中,我们会介绍如何在游戏中添加怪物,请大家继续关注!