Unity 2D教程|平台游戏(中)

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

最终效果如下:


示例工程下载地址:
游客,如果您要查看本帖隐藏内容请回复

添加跳跃

下面来为游戏主角Rushdy添加跳跃。首先,将右边的箭头移到左下角,与左箭头放在一起。然后,在右下角新增一个按钮,用来实现“跳跃”。



打开上篇教程中编写的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脚本代码如下: 


此时点击键盘上的空格键,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拖拽至该字段。


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


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


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


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

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

利用Prefab创建平台

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


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

添加障碍物

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


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

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

[C#] 纯文本查看 复制代码
public class Hazard : MonoBehaviour
{
    private Controls player;
    public Transform start;
 
    void Start()
    {
        player = FindObjectOfType();
    }
  
    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对象上。

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


新建脚本命名为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”,这样玩家就可以从其上方跳过。


玩家死亡

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


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

[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class DestroyParticle : MonoBehaviour
{
    private ParticleSystem thisParticleSystem;
 
    void Start()
    {
        thisParticleSystem = GetComponent();
    }
 
    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().velocity = Vector3.zero;
    player.GetComponent().enabled = false;
    yield return new WaitForSeconds(1);
    player.transform.position = start.position;
    player.GetComponent().enabled = true;
    player.enabled = true;
}

上面的代码为角色死亡的动画加入了等待时间,这样主角在死亡和再次出现之间就有了间隔,不会显得太过突兀。另外,为了更好的游戏体验,您还要将死亡后的角色设为不可操作的,并且删除所有的动量,以防止再次开始游戏时主角是有加速度的。

下一篇

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


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

最终效果如下:

原文作者: Adam Sinicki

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论