请选择 进入手机版 | 继续访问电脑版

查看: 40864|回复: 235

[原创] Unity 2D教程|平台游戏(中)

  [复制链接]

1278

主题

1985

帖子

2万

贡献

管理员

Rank: 9Rank: 9Rank: 9

积分
26195
QQ
发表于 2016-11-10 05:41:10 | 显示全部楼层 |阅读模式
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<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对象上。

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


新建脚本命名为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<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让角色跳得更高等等。您也可以按照自己的喜好根据自己的想法,自由调整这些属性的数值。


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

最终效果如下:


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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

3

主题

22

帖子

285

贡献

初级UU族—3级

Rank: 3Rank: 3

积分
285
发表于 2016-11-10 06:42:43 | 显示全部楼层
厉害呢,我的楼主

0

主题

6

帖子

80

贡献

初级UU族—2级

Rank: 2

积分
80
发表于 2016-11-12 02:18:17 | 显示全部楼层
很棒哦

0

主题

11

帖子

75

贡献

初级UU族—2级

Rank: 2

积分
75
发表于 2016-11-13 05:50:06 | 显示全部楼层
感谢楼主分享

0

主题

4

帖子

60

贡献

初级UU族—2级

Rank: 2

积分
60
发表于 2016-11-13 07:54:10 | 显示全部楼层
期待最后一部分

0

主题

4

帖子

60

贡献

初级UU族—2级

Rank: 2

积分
60
发表于 2016-11-13 16:22:29 | 显示全部楼层
本帖最后由 狼虎灭却 于 2016-11-13 16:28 编辑

官方论坛应该多出点教程嘛,感觉人不是很多的样子

0

主题

8

帖子

110

贡献

初级UU族—2级

Rank: 2

积分
110
发表于 2016-11-14 05:44:03 | 显示全部楼层
感谢分享……

0

主题

1

帖子

15

贡献

初级UU族—1级

Rank: 1

积分
15
发表于 2016-11-14 07:35:27 | 显示全部楼层
不错不错

0

主题

9

帖子

235

贡献

初级UU族—3级

Rank: 3Rank: 3

积分
235
发表于 2016-11-14 13:33:00 | 显示全部楼层
感谢楼主分享

0

主题

3

帖子

45

贡献

初级UU族—1级

Rank: 1

积分
45
发表于 2016-11-14 15:23:49 | 显示全部楼层
这是一个回复hhh,不过这个实例真的很好啊.但是有人告诉我说二维的东西没必要添加刚体...求解释...
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表