Unity制作FlappyBird教程1

用Unity制作游戏确实“多快好省”。作为一个新手,需要大量的练习制作游戏,才能以最快速度熟悉Unity。本项目的代码可以在 Github 上欢迎下载。PS: 本教程的代码位置在 Tag “v1.0”。

FlappyBirdGame.gif

在开始本教程前,你至少要对Unity2D有一个初步了解。至少要学习过了官方的UFO 2D项目。如果没有学习过,强烈建议先学习一下。官网上的视频被墙了,但是目在B站上有搬运。

准备工作

首先新建一个2D项目,命名为FlappyBird。

然后创建好如下文件夹:
Unity制作FlappyBird教程1_第1张图片

下载好资源,放入我们项目中。我们需要的资源在工程相关目录下可以找到。

Unity制作FlappyBird教程1_第2张图片
使用到的图片资源

Unity制作FlappyBird教程1_第3张图片
使用到的音频资源

实现游戏背景环境

游戏看起来是小鸟在飞,实际上,为了方便实现,我们可以理解为小鸟不动,是背景在往后移动。

先找到background资源导入时修改为Sprite,Sprite Mode: Single,Pixels Per Unit: 32。然后 Apply。
Unity制作FlappyBird教程1_第4张图片

同样对land,pipe1,pipe2执行类似的操作,知识注意Pivot锚点的位置。land为Top,pipe1为Top, pipe2为Bottom。更改锚点是为了之后布局更方便。

创建背景和地面

Hierarchy 下创建一个空游戏对象。Hierarchy->Create->Create Empty。命名为Ground,再在其子对象中创建一个MovingGround1。将background, land拖入。


Unity制作FlappyBird教程1_第5张图片

接着我们要设置position: background:(0,2,0)、land(0,-3,0)。

设置SortLayer: 默认情况下,我们的Sprite加入后都是Default层,故我们要给land更高一些。点击 SortingLayer -> Add Sorting Layer 来增加四个SortLayer: Background,Pipes,Foreground, Player。然后给background设为Background,land设置为Foreground。也可以在菜单Eidt->ProjectSettings->Tags&Layers去设置。所以我们的图层排序就是从下到上: Background->Pipes->Foreground->Player。

Unity制作FlappyBird教程1_第6张图片
Tags&Layers

当然你可以都使用Default,然后去更改Order in Layer。在我们这个小游戏中并没什么关系,但是如果游戏复杂以后,最好使用Sorting Layer。

给MovingGround1添加物理系统组件 :Box Collider 2D组件,Rigidbody 2D组件。

Unity制作FlappyBird教程1_第7张图片

添加Box Collider 2D时,要正好把land上部包含,以便之后能正确的和小鸟发生碰撞检测。

让我们把背景动起来吧!在Scripts下创建MovingGround.cs。并将它们绑定到MovingGround1中。

// MovingGround.cs
public class MovingGround : MonoBehaviour {

    public float speed = 2;
    private Rigidbody2D rb2D;

    void Awake() {
        rb2D = GetComponent();
        rb2D.velocity = new Vector2(-speed, 0);
    }
    void Update() {
        //if (GameController.instance.isGameOver) { 
          //  rb2D.velocity = Vector2.zero;
        //}
    }
}

顾名思义,这个脚本会让物体向后移动起来。它之后同样可以用到我们的其他“不动的物体”例如:管道。

现在运行一下,看看,我们的背景开始往后移动了。但是好像很糟,因为图片比较窄,并没有把屏幕包含满。

接下我们设置下摄像机:
Unity制作FlappyBird教程1_第8张图片
image.png

然后我们将MovingGround1拖入到 Project->Prefabs,作为预制体。然后Ctrl+D(Mac: CMD+D)复制另外三个出来。调整Transform.Position让他们横排排列好。最终MovingGround1,2,3,4的位置为:(-7,-1.7,0)、(2,-1.7,0)、(11,-1.7,0)、(20,-1.7,0)。


Unity制作FlappyBird教程1_第9张图片
Hierarchy中的样子

Unity制作FlappyBird教程1_第10张图片
Scene中的样子

这样,我们的4个背景形成一个整体,一起往后移动。接下来只要让他们移动到看不见的位置时,又重新移动到开始的位置即可。这样我们的环境就可以不断的移动,永远不会停下来了。

给MovingGround1添加脚本LoopGround.cs,并要Apply一下,让其他三个同样拥有这个脚本组件。

// LoopGround.cs
public class LoopGround : MonoBehaviour {

    private BoxCollider2D groundCollider;
    private float boxColliderWidth;

    void Start() {
        groundCollider = GetComponent();
        boxColliderWidth = groundCollider.size.x;
    }
    
    void Update () {
        // 到看不见的位置后,立马移动到最初的位置
        if (transform.position.x < -2 * boxColliderWidth) {
            transform.position = new Vector3(
                transform.position.x + 4 * boxColliderWidth,
                transform.position.y,
                transform.position.z);
        }
    }
}

很好,我们的背景和地面就完成了。

小鸟

首先同样我们将资源导入。注意,我们这个图片是一个帧动画的序列图,需要分割一下。点击 Sprite Editor。
Unity制作FlappyBird教程1_第11张图片

Unity制作FlappyBird教程1_第12张图片

完成后,点击Apply,图片就切好了。

制作玩家对象。我们将birds_0拖入Hierarchy,并修改为Player,设置Tag为Player,并设置位置,设置Sorting Layer为Player,否则将看不到。

Unity制作FlappyBird教程1_第13张图片

添加动画。选中birds_0,birds_1,birds_2,一起拖到Player上,这时弹出保存为动画的选项框,保存为BirdFly.anim。并将其存到Assets/Animations下。这时Animations下多出两个文件,一个是birds_0的AnimatorController文件,一个BirdFly的Animation文件。我们修改birds_0为Bird,然后双击,这时就会打开Animator的窗体。默认情况下,我们的精灵Player就会自动执行BirdFly的动画。

为小鸟添加物体系统组件

Unity制作FlappyBird教程1_第14张图片
image.png

添加脚本Bird.cs

// Brid.cs
public class Bird : MonoBehaviour {

    public float upBounce = 300;

    private Rigidbody2D rb2D;

    private void Awake() {
        rb2D = GetComponent();
        anim = GetComponent();
    }

    private void Update() {
        if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0)) {
            Fly();
        }
    }

    private void OnCollisionEnter2D(Collision2D collision) {
        Debug.Log("Bird Dead, Game Over!");
    }

    private void Fly() {
        rb2D.velocity = Vector2.zero;
        // 添加一个向上的力,使得小鸟向上飞
        Vector2 upForce = Vector2.up * upBounce;
        rb2D.AddForce(upForce);
        //SoundManager.instance.PlayFly();
    }

    private void Die() {
        rb2D.velocity = Vector2.zero;
        //GameController.instance.GameOver();
    }
}

这时,我们运行看看,我们的小鸟可以自由自在的飞翔了。就下来就只差管道了。

障碍物:管道

管道在之前已经被导入了,由于我们的图片资源一个向下,一个向上,所以特地设定了Pivot为Bottom和Top。这样我们将它们组成一个整体时,可以以中心对称。

我们创建一个Pipes空对象,来作为两根管的父对象。并设置位置和BoxCollider2D。
Hierarchy中的样子

这里记得将MovingGround.cs脚本组件添加到Pipes上,这样管道才会跟着背景一起移动。注意,我们要为pipe1,pipe2的SortLayer设置为Background。
Unity制作FlappyBird教程1_第15张图片
pipe2的Inspector

Unity制作FlappyBird教程1_第16张图片
pipe1的Inspector

我们要为Pipes父对象添加碰撞检测区域和刚体组件。


Unity制作FlappyBird教程1_第17张图片
Pipes1的Inspector

最后的样子如下,其中标记的1就是小鸟在通过时,可以检测到小鸟通过了,可以进行加分的功能。
Unity制作FlappyBird教程1_第18张图片
image.png

然后我们添加碰撞检测的逻辑,实现这个加分吧。给Pipes添加自定义脚本Pipes.cs

// Pipes.cs
public class Pipes : MonoBehaviour {

    private void OnTriggerEnter2D(Collider2D collision) {
        // 管道的中间位置的探测区域,如果碰撞物体为小鸟(被标记为了Player),计分
        if (collision.tag == "Player") {
            Debug.Log("You are good!");

            //GameController.instance.PassOnePip();
            //SoundManager.instance.PlayPass();
        }
    }
}

好的,完成了,运行一下。(好吧,我看着总觉得会有马里奥从管道里爬出来。:)

游戏管理

项目到这里为止,我们还只有一个管道。随着场景的移动,我们当然需要不停的添加管道。这里我们添加一个GameController。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameController : MonoBehaviour {

    public static GameController instance = null;

    // 管道预制件
    public GameObject pipesPrefabs;

    public Text countText;
    public GameObject gameOverTips;

    // 管道产生的频率,每几秒产生一个
    public float createPipesRate = 3f;

    // 管道中心位置的y最小值
    public float minPipPosY = -1f;
    // 管道中心位置的y最大值
    public float maxPipPosY = 4f;
    // 初始化管道的位置,x最好为负数不可见位置
    public Vector2 startPipPos = new Vector2(-12f, 0f);

    // 统计已经成功过了几个管道
    private int count = 0;
    // 小鸟是否已经死了
    [HideInInspector] public bool isGameOver;

    // 上一次创建出管道的时间
    private float lastCreatePipTime = float.NegativeInfinity;

    // 缓存管道的链表,用来复用管道
    private List pipes = new List();
    // 管道缓存的个数
    private const int PIPESTOTAL = 8;
    // 当前管道下标,用来更新管道
    private int currPipesIndex = 0;

    private void Awake() {
        if (instance == null) {
            instance = this;
        } else if (instance != this) {
            Destroy(gameObject);
        }
    }

    private void Start() {
        isGameOver = false;
        gameOverTips.SetActive(false);
        // 开始时,创建出管道缓存
        InitPipesPool();
    }

    private void Update() {

        // 当可以创建出管道时,拿出缓存中一个管道来更新位置
        if (!isGameOver && lastCreatePipTime + createPipesRate < Time.time) {
            
            lastCreatePipTime = Time.time;

            UpdatePipesPosition();
            currPipesIndex = (currPipesIndex + 1) % PIPESTOTAL;
        }

        if (isGameOver && Input.GetKeyDown(KeyCode.Space)) {
            GameRestart();
        }
    }

    public void PassOnePip() {
        count++;
        countText.text = "Count: " + count.ToString();
    }

    public void GameOver() {
        if (isGameOver) return;

        isGameOver = true;
        gameOverTips.SetActive(true);
    }

    private void GameRestart() {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    }

    // 初始化管道缓存池
    private void InitPipesPool() {
        for (int i = 0; i < PIPESTOTAL; ++i) {
            GameObject obj = Instantiate(pipesPrefabs, startPipPos, Quaternion.identity);
            pipes.Add(obj);
        }
    }

    // 更新当前管道的位置
    private void UpdatePipesPosition() {
        float randomPosY = Random.Range(minPipPosY, maxPipPosY);
        Vector2 position = new Vector2(10f, randomPosY);
        pipes[currPipesIndex].transform.position = position;
    }
}

GameController管理了一个Pipes的管道池来复用管道,就不用不停的创建和销毁了。通过一次创建,之后每隔createPipesRate秒钟就刷新一个管道的位置,让他移动到适合的位置。

然后我们需要将Hierarchy中的Pipes拖到Project/Prefabs作为预制体。Hierarchy中的需要删掉。之后管道就都由GameController来管理了。

添加基本UI。我们像 UFO项目一样添加基本的UI。这里就不详细解释了。

Unity制作FlappyBird教程1_第19张图片
Hierarchy中的UI对象

Unity制作FlappyBird教程1_第20张图片
Scene

Hierarchy创建一个空游戏对象,命名为GameController。并将上面GameController.cs脚本组件关联上。并将内容补充完整。


Unity制作FlappyBird教程1_第21张图片

音效

最后,我们添加一些简单的音效吧。新建一个SoundManager的空游戏对象,添加AudioSource组件,并创建脚本SoundManager.cs。


Unity制作FlappyBird教程1_第22张图片
image.png
using UnityEngine;

public class SoundManager : MonoBehaviour {

    public static SoundManager instance = null;

    public AudioClip flyClip;
    public AudioClip dieClip;
    public AudioClip pointClip;

    private AudioSource audioSource;

    void Awake() {
        if (instance == null) {
            instance = this;
        } else if (instance != this) {
            Destroy(gameObject);
        }

        audioSource = GetComponent();
    }

    public void PlayFly() {
        audioSource.clip = flyClip;
        audioSource.Play();
    }

    public void PlayDie() {
        audioSource.clip = dieClip;
        audioSource.Play();
    }

    public void PlayPass() {
        audioSource.clip = pointClip;
        audioSource.Play();
    }
}
Unity制作FlappyBird教程1_第23张图片

将之前代码里SoundManager有关代码反注释。最后,我们运行。

到这里,我们的FlappyBird就基本完成了。给自己点一个大大的赞吧!:)。如果有什么问题,欢迎在下面评论。

FlappyBird 教程2

你可能感兴趣的:(Unity制作FlappyBird教程1)