在2D平台游戏上篇的教程中,我们为大家介绍了如何去创建主角及平台、添加物理碰撞,以及键盘和、添加键盘及触摸控制相关的内容。这一篇将继续讲解如何添加角色跳跃、角色坠落及自动生成平台等。

最终效果如下:

133433p1n83vmvum3lcjmj.jpg
133433y44ncdxn88ad8x4j.jpg
打开上篇教程中编写的Controls脚本,加入两个公有公共变量,分别是bool类型的jump,以及float类型的jumpheight。可以在检视面板中设置jumpheight的值,这里设为8。然后在脚本中加入以下代码:

[C#] 纯文本查看 复制代码if (Input.GetKey(KeyCode.Space)) { rb.velocity = new Vector2(rb.velocity.x, jumpheight); } if (jump) { rb.velocity = new Vector2(rb.velocity.x, jumpheight); jump = false; }
最终Controls脚本代码如下:

133433l9jr541i8jesrisn.jpg
此时点击键盘上的空格键,Rushdy就可以跳跃了。与上篇添加移动的方法类似,这里也有一个可以通过Touch脚本来控制的bool变量,用来控制是否跳跃。这次的跳跃仅在角色的Y轴方向赋予了一个向上的添加了加速度,现在将上篇教程编写的Touch脚本拖拽至刚刚新建的“跳跃”按钮上。然后在Touch脚本中加入以下代码:

[C#] 纯文本查看 复制代码public void Jump() { player.jump = true; }
下面为“跳跃”按钮添加事件触发器,这里只需要一个事件类型“Pointer Down”,响应函数为“Jump”。如果您依旧不了解这里的操作步骤,请查看上篇教程添加触摸控制部分的内容。由于跳跃不需要保持按键按下的状态,一次按下即可触发,所以这里不需要“jumpRelease”这样的函数。

这里可以先禁用触摸控制,只需在层级视图(Hierarchy)中选中Canvas,然后取消勾选检视面板左上方的蓝色框即可。但是在制作移动版本进行打包APK之前,记得要重新勾选该框,启用触摸控制,这样才能在手机上进行流畅地操作。

让角色降落

现在的问题是,如果玩家一直按空格键,角色就会一直跳跃。因此所以要加入判断,必须落地之后才能再次跳跃。

可以用Raycast来检测角色落地,但更简单的方法是判断角色下方的坐标是否在地面以下。在Controls脚本中新建一个Transform,命名为groundCheck,就是角色下方的坐标。并添加一些的变量:

[C#] 纯文本查看 复制代码public Transform groundCheck; public float groundCheckRadius; public LayerMask whatIsGround; private bool onGround;
groundCheckRadius为角色下方的坐标点指定一个范围,whatIsGround是标记地面的LayerMask,onGound则用来检测是否在地面上。再在Controls脚本中加入以下函数:

[C#] 纯文本查看 复制代码void FixedUpdate() { onGround = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround); }
FixedUpdate与Update函数类似,区别在于Update与屏幕刷新率息息相关,而FixedUpdate的行为更加容易预测,因为在Unity中设置的FixedUpdate每帧间隔的时间是固定的,所以它更适用于物理相关的代码。上面的代码就是在角色下方的坐标点位于地面某个半径范围内时,就将onGround设为“true”。下面来设置groundCheck,回到Unity编辑器中新建GameObject命名为Check Ground,作为主角Rushdy的子对象。

在层级视图中选中主角,可以看到检视面板上Controls脚本的“Ground Check”字段为“None”,将刚刚新建的游戏对象Check Ground拖拽至该字段。

133433iqaggqg1qq48a4my.jpg
在层级视图中双击Check Ground对象,利用移动工具将该对象移动至主角的正下方。

133433t3t8wwef9y83a2fk.jpg
再次点击主角rushdy,将Controls脚本的radius值设为0.1,并将主角的Tag设为“Player”。下面为地面添加新的层标记,添加名为“Ground”的Layer。在层级视图点击ground对象,从检视面板的“Layers”下拉列表中选择“Add Layer”:

133434aupevuvqceglg0oe.jpg
在第一个可修改的文本框中输入“Ground”:

133434ipaq2q8wwal1mk1f.jpg
回到ground对象的检视面板,现在可以将Layers设为“Ground”了。同样在rushdy的检视面板中,将Controls脚本的whatIsGround也设为“Ground”。

这时点击运行,主角就不能无限跳跃了!

利用Prefab创建平台

下面利用Prefab为平台加入一些变化。在Assets目录下新建文件夹“Prefabs”,用于存放项目中需要的Prefab。将ground对象从层级视图拖拽至Prefabs文件夹下,Unity会自动将其保存为Prefab。然后从Prefabs文件夹中拖拽ground到场景的任意位置,按照您的喜好来根据自己的想法来设计设置平台。

133434uonxoenef11pr1xa.jpg
为了避免主角与平台之间的摩擦力可能导致主角被“卡住”的情况,先选中层级视图中的ground对象,在检视面板中勾选上Box Collider 2D组件的“Used By Effector”选项,然后为ground添加“Platform Effector 2D”组件,并取消勾选“Use One Way”,这样就能以防止角色从平台下方穿过。

添加障碍物

下面加入一些锯齿状的障碍物spikes,在平台上添加一些Sprite,Sprite图片如下:

133434wd6qpsizpz3s33eq.jpg
同样为锯齿状障碍物添加多边形碰撞组件Polygon Collider 2D,并勾选“Is Trigger”。障碍物与平台不一样,这里障碍物作为被碰撞体,可以用代码定义碰撞体的行为。

新建C#脚本命名为“Hazard”,代码如下:

[C#] 纯文本查看 复制代码public class Hazard : MonoBehaviour { private Controls player; public Transform start; void Start() { player = FindObjectOfType<Controls>(); } void Update() { } void OnTriggerEnter2D(Collider2D other) { if (other.tag == Player) { player.transform.position = start.position; } } }
当有物体碰撞到障碍物时,就会触发OnTriggerEnter2D函数,即在2D碰撞体刚刚发生碰撞触发的方法。通过该函数然后检测该物体是否是主角。如果是,则游戏结束,主角回到起始位置。

然后将障碍物保存成Prefab,再按照您的喜好将障碍物拖拽并放置到场景中。如果层次显示有问题,请调整Prefab的“Order In Layer”属性。您可,将该数值设置为玩家与背景的值之间,即让障碍物显示在玩家前方,而在Ground背景后方。

回到Unity编辑器新建GameObject命名为Start,将其放在每次游戏开始时玩家的起始位置。然后将Harzard脚本绑定到障碍物spikes对象上。

另外还可以加入一些障碍物,如随机移动的敌人:

133434s7nenq874qjrqqqx.jpg
新建脚本命名为ObjectMove,代码如下:

[C#] 纯文本查看 复制代码using UnityEngine; using System.Collections; public class ObjectMove : MonoBehaviour { public float amounttomovex; public float speed; private float currentposx; private float currentposy; private int facing; void Start() { currentposx = gameObject.transform.position.x; facing = 0; } void Update() { if (facing == 1 gameObject.transform.position.x < currentposx - amounttomovex) { facing = 0; } if (facing == 0 gameObject.transform.position.x > currentposx) { facing = 1; } if (facing == 0) { transform.Translate(Vector2.right * speed * Time.deltaTime); } else if (facing == 1) { transform.Translate(-Vector2.right * speed * Time.deltaTime); } } }
可以在检视面板设置敌人移动的速度与距离。将Harzard脚本添加到敌人身上,现在点击运行,这样在游戏运行时,一旦玩家在撞到障碍物或敌人时,就都会导致游戏结束。

还有个问题就是玩家可以不断坠落。解决办法是复制一个平台作为玩家坠落的终点,重命名为“bounds”,删掉上面的Sprite,然后为其添加“Harzard”脚本用来结束玩家的生命。

另外这里还加入了另一种敌人,它不会结束玩家的生命,但会将玩家推出平台。这两种敌人都需要添加带有Circle Collider 2D组件,但后者没有“Harzard”组件,并且将其Layer设为“Ground”,这样玩家就可以从其上方跳过。

133434n8ib1nchunelqkvk.jpg
玩家死亡

到目前位置,玩家死亡前后还没有什么明显的表现效果。,只是玩家消失之后,又会出现在起始位置。下面加入玩家死亡的效果。依次点击“Game Object > Particle System”创建粒子系统,命名为“blood”。双击粒子系统,在检视面板中调整各属性的值,如是否循环、粒子大小随时间变化、粒子生成频率、粒子颜色等等。您可以自行调整至合适的效果,不需要循环,30秒即可,这里将颜色设为红色。

133434spp191qi1eep8e89.jpg
新建脚本DestroyParticle,在粒子动画播放结束时删除整个粒子系统。代码如下:

[C#] 纯文本查看 复制代码using UnityEngine; using System.Collections; public class DestroyParticle : MonoBehaviour { private ParticleSystem thisParticleSystem; void Start() { thisParticleSystem = GetComponent<ParticleSystem>(); } void Update() { if (thisParticleSystem.isPlaying) { return; } Destroy(gameObject); } }
将DestroyParticle脚本拖拽至“blood”对象上,然后将“blood”保存为Prefab。

然后在Harzard脚本中声明GameObject类型变量Explode,并在onTriggerEnter函数中移动主角的代码前面,添加如下代码:

Instantiate(Explode, player.transform.position, player.transform.rotation);

Instantiate顾名思义就是“实例化”,它用来“创建”游戏对象,生成敌人也会用到它。另外还可以在Harzard脚本中加入以下代码让角色死亡效果更流畅:
[C#] 纯文本查看 复制代码void OnTriggerEnter2D(Collider2D other) { if (other.tag == Player) { StartCoroutine(respawndelay); } } public IEnumerator respawndelay() { Instantiate(Explode, player.transform.position, player.transform.rotation); player.enabled = false; player.GetComponent<Rigidbody2D>().velocity = Vector3.zero; player.GetComponent<Renderer>().enabled = false; yield return new WaitForSeconds(1); player.transform.position = start.position; player.GetComponent<Renderer>().enabled = true; player.enabled = true; }
上面的代码为角色死亡的动画加入了等待时间,这样主角在死亡和再次出现之间就有了间隔,不会显得太过突兀。另外,为了更好的游戏体验,您还要将死亡后的角色设为不可操作的,并且删除所有的动量,以防止再次开始游戏时主角是有加速度的。

下一篇

事实上,教程到此现有的这个游戏内容已经比较完整了,当然您还可以继续打磨。例如:加入一些音效在玩家移动及死亡时播放,轻微调整相机将“Field of View”设为70,粘贴一些背景图以防平台超出边界,将jumpheight设为8.5让角色跳得更高等等。您也可以按照自己的喜好根据自己的想法,自由调整这些属性的数值。

133435va0s0r32zaj06zrz.jpg
第二篇的内容就到这里,还有更多精彩内容留待下一篇继续讲解。

最终效果如下:
133435arpg607k0jsk3gph.jpg

原文连接:How to create a simple 2D platformer for Android in Unity – Part two
原文作者: Adam Sinicki
转载请注明来源:Unity官方中文社区(forum.china.unity3d.com)。请勿私自更改任何版权说明信息。 Unity, 平台游戏, 教程锐亚教育

锐亚教育 锐亚科技 unity unity教程