Unity 2D Flappy Bird Tutorial

来源:互联网 发布:网络运营培训 编辑:程序博客网 时间:2024/06/05 11:21

Unity 2D Flappy Bird Tutorial

Unity 2D Flappy Bird Game

Foreword

In this Tutorial we will learn how easy it is to make a game like Flappy Bird in Unity. Flappy Bird was released in 2013 and became the most downloaded iOS App in January 2014.

The gamedesign is very simple: a bird is supposed to fly horizontally between obstacles, and the player can press a button to make the bird flap and fly upwards. Simple games like that are always perfect for a Tutorial, all we need are 40 lines of code and a few sprites.

As usual, everything will be explained as easy as possible so everyone can understand it.

Requirements

Knowledge

Our Tutorial does not require any special skills. If you know your way around Unity and heard about GameObjects and Transforms before, then you are ready to go. And if you didn't, don't worry about it too much.

Feel free to read our easier Unity Tutorials like Unity 2D Pong Gameto get used to the engine.

Unity Version

Our Flappy Bird Tutorial will use Unity 5.0.0f4. Newer versions should work fine as well, older versions may or may not work. The free version of Unity 5 now comes with all the engine features, which makes it the recommended version.

Project Setup

Let's get to it. We will start Unity and select New Project:
Unity New Project

We will name it flappybird, select any location like C:\, select 2D and click Create Project:
Unity Create new 2D Project

If we select the Main Camera in the Hierarchy then we can set theBackground Color to a light blue (R=198, G=208, B=230) for the sky color and adjust the Size like shown in the following image:
Camera Properties

The Background

We will begin by drawing a very simple sky background in our drawing tool of choice:
Flappy Bird Background
Note: right click on the image, select Save As..., navigate to the project's Assetsfolder and save it in a new Sprites folder.

After saving it, we can select the background in the Project Area:
Background in Project Area

And then modify the Import Settings in the Inspector:
Background Import Settings
Note: a Pixels Per Unit value of 16 means that 16 x 16 pixels will fit into one unit in the game world. We will use this value for all our textures, because the Bird will be 16 x 16 pixels, which should end up being 1 unit in the game world.

Alright so let's add the background to the game world by dragging it from the Project Area onto the Main Camera in the Hierarchy:
Background to Hierarchy

So that the background becomes a child of the Main Camera:
Background as Child of Camera

Now that the background is a child of the camera, it will always go where the camera goes. Or in other words, the player will always see the background.
Note: we could also place several backgrounds next to each other so that there is still a background when the camera moves horizontally, but making it a child of the camera is much easier.

Let's take a look at the Inspector and position the background one unit lower at Y=-1, just so that it fits to the rest of the game later on:
Background position

If we press Play then we can already see the background sky:
Background in Scene

There is one more adjustment to be made here. We will add the bird and some obstacles soon, so let's also make sure that the background is really drawn behind everything else. Unity uses the SpriteRenderer'sSorting Layer and Order in Layer properties to decide which parts of a game should be in front of which other parts.

We will simply set the Order in Layer to -1 so that everything else will be drawn in front of it:
Background Order in Layer
Note: the higher the order, the more it is in the foreground. The lower the order, the more it is in the background.

The Ground

Let's also draw some kind of terrain for the ground. We will make it very wide so that there is enough space for our obstacles later:
Flappy Bird Ground
Note: right click on the image, select Save As... and save it in the project'sAssets/Sprites folder.

We will select the ground in the Project Area and then assign the sameImport Settings that we used before:
Ground Import Settings

Afterwards we will drag it from the Project Area into the Hierarchyagain:
Add Ground to Hierarchy
Note: this time we won't make it a child of the camera.

Let's take a look at the Inspector and position the ground at X=16Y=-6: so that it is below the background and so that most of the area is at the right of the screen:
Ground position

This time we will select a Order in Layer value of 1, so that it will always be in front of the bird and the obstacles later on:
Ground Order in Layer

Ground Physics

The ground should the part of the physics world. Right now it is really just an image in the game world, just a visual effect and nothing more. We want the ground to be like a wall that the bird can collide with, so let's select Add Component->Physics 2D->Box Collider 2D in the Inspector:
Ground Collider

Normally we would be done now, but there is one more adjustment to be made here. Later on we will add obstacles to our game (like the green pipes in the original Flappy Bird game), and those obstacles will move upwards and downwards into the ground. The obstacles and the ground will both be part of the physics world, and according to the laws of physics, there can never be two objects at the same place (or in our case, two Colliders).

There are several ways to work around this. As usual we will choose the easiest way by creating a new physics Layer that we will use for the ground and the obstacles. Afterwards we will tell Unity to simply ignore collisions in-between that layer.

We can create a new layer by selecting Add Layer in the Inspector:
Layer

Afterwards we will add one User Layer, let's call it WeirdPhysics:
Weird Physics Layer

Now we can select the ground in the Hierarchy again and then assign the WeirdPhysics layer:
Ground WeirdPhysics Layer

Afterwards we select Edit->Project Settings->Physics 2D from the top menu and disable the WeirdPhysics vs. WeirdPhysics collisions in theLayer Collision Matrix:
Physics ignore WeirdPhysics Layer Collisions
Note: it's very rare that we have to do this in Unity, but our Flappy Bird game is one of those exceptions.

Now the ground will never collide with any of the obstacles.

Also if we press Play then we can see the sky and the ground already:
Ground in Scene

The Bird

The Bird Image

Alright, let's get to the most important part of our game: the bird. We will begin by drawing a bird flying animation with 4 frames:
Bird Animation
Note: right click on the image, select Save As... and save it in the project'sAssets/Sprites folder.

We will use the following Import Settings for it:
Bird ImportSettings

Our bird image contains several smaller images, hence it's important that we select Multiple as Sprite Mode. Afterwards we can click theSprite Editor button:
Bird Sprite Editor Button

In the Sprite Editor we Slice it as a 16 x 16 Grid:
Bird SpriteEditor Settings

After pressing the Slice button we can close the Sprite Editor. Unity will ask us if we want to apply the Unimported Import Settings, so let's select Apply.

Now we can see our 4 slices as children of the bird image in theProject Area:
Bird Children

The Bird Animation

Let's select all the slices and then drag them into the Hierarchy:
Drag Bird Slices to Hierarchy

Unity knows that we want to create an animation from those slices, which is why it asks us where to save the animation files. We will create a new BirdAnimation folder and then save the animation asfly.anim.

Afterwards we can see two new files in our BirdAnimation folder:
Bird Animation Files

The bird_0 file is the state machine that takes care of animation states and speeds. The second file is the fly animation itself. Let's double click the bird_0 file really quick so that we can see the animation state machine:
Bird in Animator
Note: we don't have to worry about the animation states because we only have one animation.

We will click on the fly state and then simply decrease the speed to 0.5in the Inspector:
Bird Fly Animation Speed

And since we only have one animation, we are already done here. If we press Play then we can even see it in action:
Bird animated

Bird Physics

Our bird is supposed to be part of the physics world. Let's begin by giving it a Collider, just like we did with the ground. We will selectAdd Component->Physics 2D->Circle Collider 2D in the Inspector:
Bird Collider

Now everything in the physics world that is supposed to move around will also need a Rigidbody. A Rigidbody takes care of things like gravity, velocity and movement forces. We can add a Rigidbody by selecting Add Component->Physics 2D->Rigidbody 2D in theInspector. We will also enable the Fixed Angle property so that the bird doesn't suddenly start rotating:
Bird Rigidbody

If we press Play then we can already see the Rigidbody's gravity property in action:
Bird Gravity

The Bird Movement Script

Our bird already looks pretty decent, but it should also fly towards the right at all times, and it should flap its wings to fly upwards if the user presses a button.

This kind of behavior can be implemented with a Script. Let's selectAdd Component->New Script in the Inspector, name it Bird and selectCSharp as the language. We will also create a new Scripts folder in our Project Area so that we can put the Bird Script into it:
Bird Script in Project Area

We can double click the Script in order to open it:

using UnityEngine;
using System.Collections;

public class Bird : MonoBehaviour {

    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}

We can make the bird fly towards the right at all times by first adding a new speed variable and then using the Rigidbody's velocityproperty:

using UnityEngine;
using System.Collections;

public class Bird : MonoBehaviour {
    // Movement speed
    public float speed = 2;

    // Use this for initialization
    void Start () {    
        // Fly towards the right
        GetComponent<Rigidbody2D>().velocity = Vector2.right * speed;
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}

Note: the velocity is exactly the movement direction multiplied by the movement speed.

If we save the Script and press Play then we can see how the bird flies towards the right of the Screen.

Now we create a new force variable and then use our Update function to check for key presses. If the user pressed the Space key then we will make the bird fly upwards with the force:

using UnityEngine;
using System.Collections;

public class Bird : MonoBehaviour {
    // Movement speed
    public float speed = 2;
    
    // Flap force
    public float force = 300;

    // Use this for initialization
    void Start () {    
        // Fly towards the right
        GetComponent<Rigidbody2D>().velocity = Vector2.right * speed;
    }
    
    // Update is called once per frame
    void Update () {
        // Flap
        if (Input.GetKeyDown(KeyCode.Space))
            GetComponent<Rigidbody2D>().AddForce(Vector2.up * force);
    }
}

If we press Play then we can now make the bird fly upwards:
Bird flapping

There is one last thing to do here. We want to restart the game as soon as the bird collided with the ground or with an obstacle. Our bird already has a Collider and a Rigidbody, which means that Unity automatically calls the OnCollisionEnter2D function. All we have to do is actually add it to our Script:

void OnCollisionEnter2D(Collision2D coll) {
    // Restart
    Application.LoadLevel(Application.loadedLevel);
}

Note: Application.LoadLevel can be used to load a Scene.Application.loadedLevel is the currently loaded Scene. Or in other words, we simply restart the current Scene.

Camera Follow

Right now the Camera never moves. And since the bird always flies towards the right of the screen, we won't be able to see it for a very long time. We will solve this problem by creating a new Script that makes the Camera follow the bird all the time.

Let's select the Main Camera in the Hierarchy and then click on Add Component->New Script, name it CameraFollow and select CSharp as the language. We will also move it into our Scripts folder and then open it:

using UnityEngine;
using System.Collections;

public class CameraFollow : MonoBehaviour {

    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}

We won't need the Start function this time, so let's remove it:

using UnityEngine;
using System.Collections;

public class CameraFollow : MonoBehaviour {
    
    // Update is called once per frame
    void Update () {
    
    }
}

Let's add a public Transform variable to specify which target to follow:

using UnityEngine;
using System.Collections;

public class CameraFollow : MonoBehaviour {
    // The Target
    public Transform target;
    
    // Update is called once per frame
    void Update () {
    
    }
}

Note: we can set that target in the Inspector later on.

Afterwards we will simply use the Update function to always set the Camera's X position to the target's X position:

// Update is called once per frame
void Update () {
    transform.position = new Vector3(target.position.x,
                                     transform.position.y,
                                     transform.position.z);
}

Note: the X position is the horizontal position.

Now our Script is done. However it's usually considered best practice to do Camera movement after everything else in the Scene was updated. We will simply change our Update function to LateUpdate, just to have it perfectly smooth:

void LateUpdate () {
    transform.position = new Vector3(target.position.x,
                                     transform.position.y,
                                     transform.position.z);
}

If we save the Script then we can take a look at the Inspector and drag the bird_0 GameObject from the Hierarchy into the Script's Targetslot:
Camera Follow Target

If we press Play then we can now see how the Camera automatically follows the bird:
Camera following the Bird

The Obstacles

The Obstacle Image

Right now our game is not very hard. We can change that by adding some obstacles. Let's draw one:
Obstacle
Note: right click on the image, select Save As... and save it in the project'sAssets/Sprites folder.

We will use the following Import Settings for it:
Obstacle ImportSettings

And then drag it from the Project Area into the Hierarchy in order to create a GameObject from it:
Obstacle in Hierarchy

We will position it at X=3Y=-5:
Obstacle Position

Here is how it looks in the Scene:
Obstacle in Scene

Obstacle Physics

The obstacle should be part of the physics world again. The bird should be able to collide with it, so let's select Add Component->Physics 2D->Box Collider 2D in the Inspector:
Obstacle Collider

We talked about how the obstacles might end up inside the ground and how we don't want the two to collide with each other, so let's make it part of our WeirdPhysics layer, too:
Obstacle Layer
Note: since we disabled collisions in-between our WeirdPhysics layer, the ground will never collide with an obstacle. The bird can still collide with the ground and with the obstacle because it has a different layer (the default one).

Alright so some of the obstacles are also supposed to move up and down. Everything in the physics world that is supposed to move will need a Rigidbody, so let's select Add Component->Physics 2D->Rigidbody 2D in the Inspector again. We don't want it to be affected by gravity, so let's set the Gravity Scale to 0. We also don't want it to rotate, so let's also enable Fixed Angle again:
Obstacle Rigidbody

If we press Play and let the bird fly against the obstacle then we can see how the level restarts:
Bird vs Obstacle

Obstacle Movement

Alright so some of the obstacles are supposed to move up and down. This kind of behavior can be implemented with a Script again. Let's select Add Component->New Script, name it Obstacle, move it into our Scripts folder and then open it:

using UnityEngine;
using System.Collections;

public class Obstacle : MonoBehaviour {

    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}

There are many different ways to make the obstacle move up and down all the time. As usual, we will use the easiest way.

We will begin by adding a speed variable and then setting the Rigidbody's velocity so that the obstacles move upwards with thespeed:

using UnityEngine;
using System.Collections;

public class Obstacle : MonoBehaviour {
    // Movement Speed (0 means don't move)
    public float speed = 0;

    // Use this for initialization
    void Start () {
        // Initial Movement Direction
        GetComponent<Rigidbody2D>().velocity = Vector2.up * speed;    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}

Now the trick is to use Unity's InvokeRepeating function to reverse that velocity every few seconds:

using UnityEngine;
using System.Collections;

public class Obstacle : MonoBehaviour {
    // Movement Speed (0 means don't move)
    public float speed = 0;
    
    // Switch Movement Direction every x seconds
    public float switchTime = 2;

    void Start() {
        // Initial Movement Direction
        GetComponent<Rigidbody2D>().velocity = Vector2.up * speed;
        
        // Switch every few seconds
        InvokeRepeating("Switch"0, switchTime);
    }
    
    void Switch() {
        GetComponent<Rigidbody2D>().velocity *= -1;
    }
}

Note: the Switch function simply reverses the Rigidbody's velocity. We then useInvokeRepeating to tell Unity to call that function every few seconds. We also added a switchTime variable to specify the time in which Switch should be called.

Let's save the Script and set the obstacle's Speed to 1:
Obstacle Script in Inspector
Note: if we don't want an obstacle to move then we can either set it's Speed to 0or disable the Script.

If we press Play then we can see our obstacle moving up- and downwards:
Obstacle moving

Adding more Obstacles

Let's right click the obstacle in the Hierarchy, select Duplicate and move it a bit further towards the right:
Duplicated Obstacle

We will also duplicate one and then set the Scale.Y property to -1:
Obstacle Scale Y-1

This way it looks properly when positioning it upside-down:
Obstacle upside-down

We can add as many obstacles with as many different speed andswitchTime properties as we want:
Unity 2D Flappy Bird Game

Summary

We just learned how incredibly easy it is to make a Flappy Bird game in Unity. We used some very powerful Unity features like Physics, Mecanim (for the animation), Layers, the Sprite Editor and Scripting. As usual now it's up to the reader to make the game fun and more difficult.

The Project Files can be download here.

0 0
原创粉丝点击