Unity3D で FlappyBird っぽいゲームを作成してみる その3

シェアする

さて、前回までで必要なパーツは揃いました。それらのパーツを組み合わせてゲームを完成させましょう。


Sponsored Links

マップの作成

このゲームでは自動でスクロールする地面と障害物, それからプレイヤーで構成されます。プレイヤーは未完成ながら一応表示されているので先にマップを作成していきましょう。

地面を生成するスクリプト

Project 欄で C# スクリプトを作成します。名前は MapController とでもしましょう。この中に地面、障害物、自動スクロールの処理を書いていきます。

まずは地面から作成します。

MapController スクリプトを開き、以下のように編集します。

public class MapController :MonoBehaviour
{
    // 地面のプレハブをここに Unity 上から設定する
    public GameObject groundPrefab;
    // 地面や障害物をセットするゲームオブジェクト
    public GameObject map;

    void Start ()
    {
        // 地面を生成するメソッドをスタートさせる
        StartCoroutine(SetGround());
    }

    IEnumerator SetGround ()
    {
        // x の値をどれだけ増やしていくか
        int offset = 10;
        int index = 0;
        while (true) {
            // 初期値に localposition を利用できないので一旦画面外に飛ばしている。
            // 画面内にするとプレイヤーとぶつかって即死するかも?
            Vector3 pos = new Vector3 (0, -90, 0);
            // 地面を作成
            GameObject ground = Instantiate (groundPrefab, pos, Quaternion.Euler (new Vector3 (-90, 0, 0))) as GameObject;
            // 地面の親要素を Map にする
            ground.transform.parent = map.transform;
            // 正しい位置に修正
            pos.y = -7.5f;
            pos.x = index * offset;
            ground.transform.localPosition = pos;
            index += 1;
            // 3秒毎にこの処理を実行する為の処理
            yield return new WaitForSeconds (3f);
        }
    }
}

解説はソースコード上を参照してください。おおざっぱにいうと3秒毎に画面の下のほうにプレハブ化していた地面を生成しつづけています。

スクリプトを編集したら Unity 上でこのスクリプトを利用できるようにします。

Hierarchy 欄で空のゲームオブジェクトを作成し、MapController とでもしておきます。そうしたらこの空のゲームオブジェクトにスクリプトをドラッグします。

スクリプトが適用されたら画面のように、Inspector に Ground Prefab と Map が表示されます。Ground Prefab に Project 欄から地面のプレハブを, Map に Hierarchy から Map をドラッグし、適用します。

create-map

この状態でゲームを実行すると地面がどんどん伸びていくと思います。

地面を動かす

生成された地面を動かします。

    void Start() {
        StartCoroutine(MoveMap());
        StartCoroutine(SetGround());
    }

    IEnumerator MoveMap ()
    {
        while (true) {
            Vector3 pos = map.transform.position;
            // Time.deltaTime で 1 フレームあたりの秒数を取得,
            // その分だけ移動させる事で一定の値だけ動かせる。
            pos.x -= 1 * Time.deltaTime;
            map.transform.position = pos;
            yield return 0;
        }
    }

map の位置を一定の速度で動かしているだけの簡単なスクリプトです。Time.deltaTime を利用するのは 1 フレームあたりの秒数が固定では無い為です。

generate-ground

障害物を生成する

あとは障害物を置きましょう。

これは地面生成とよく似たスクリプトになりますが localposition を利用しないですむので地面よりはシンプルです。それと縦位置はランダムです。

    public GameObject pipePrefab;

    void Start() {
        StartCoroutine(MoveMap());
        StartCoroutine(SetGround());
        StartCoroutine(SetPipe());
    }

    IEnumerator SetPipe ()
    {
        while (true) {
            // 縦方向ランダムの位置に設置
            // 地面が自動で動くので localposition ではなく通常の position を利用する。
            Vector3 pos = new Vector3 (3, Random.Range(-3f, 3f), 0);
            GameObject pipe = Instantiate (pipePrefab, pos, transform.rotation) as GameObject;
            pipe.transform.parent = map.transform;
            yield return new WaitForSeconds (3f);
        }
    }

編集後ゲームを実行したら障害物がランダムに現れます。

generate-pipes

だんだんゲームっぽくなっていきましたね。

プレイヤーの処理を追加

さてマップの作成は終わったので残るはプレイヤーです。現状だとプレイヤーは無敵だしスコアの計算がありません。このへんを改善してゲームを完成させます。

スコアの加算

スコアを計算できるようにしましょう。ゲームオーバー時にも表示されます。

障害物を作成した際に同時に作成した IsTrigger 付きの Box Collider はこの為にあります。Trigger に入った際にスコアを加算する、というような処理になります。

以下の処理を追加します。

    // スコア用
    private int score = 0;

    // スコアの表示の設定を行います。
    public GUIStyle guiStyle;

    // トリガーに入った時に score を加算します。
    void OnTriggerEnter2D(Collider2D collider) {
        score += 1;
        Destroy(collider); // OnTriggerEnter は1回しか呼ばれない、という認識なんですが何度も呼ばれてウボァーってなったので Destroy 呼んでます。
    }

    void OnGUI ()
    {
        // スコアを上に表示します。
        GUI.Label(new Rect(0, 0, 200, 50), "score:" + score.ToString(), guiStyle);
    }

スクリプトを編集したら、Player の Inspector で guiStyle を編集します。背景が青いので文字の色を白、文字の大きさを適当な値にすれば見やすくなると思います。

player-guistyle

実行するとこんな感じに画面上部にスコアが表示され、障害物をくぐる都度、スコアが増えていきます。

player-score

ゲームオーバーの処理を追加

プレイヤーが障害物もしくは地面にぶつかったらゲームオーバーという仕様です。ゲームオーバーになったらスコアを表示し、さらにマウスをクリックしたらゲームの開始に戻ります。Player スクリプトを修正しましょう。

    // ゲームオーバーしてるか否か
    private bool gameover = false;

    void Update() {
        // ゲームオーバー時は操作できないように。
        if (Input.GetMouseButtonDown(0) && !gameover) {
            Jump();
        }
    }

    // 何かにぶつかったら呼ばれる
    void OnCollisionEnter2D(Collision2D collision) {
        StartCoroutine(GameOver());
    }

    IEnumerator GameOver() {
        // ゲームオーバーのフラグをたてる
        gameover = true;
        // マウス連打してたらスコアが表示されずに画面が遷移するのでその対策
        yield return new WaitForSeconds(1f);
        // マウスクリックしたらゲームの最初に戻る
        while (!Input.GetMouseButtonDown(0)) { yield return 0; }
        Application.LoadLevel("Main");
    }

    void OnGUI() {
        // ゲームオーバー時はその表示を
        if (gameover) {
            GUI.Label(new Rect(0, 0, Screen.width, Screen.height), "gameover\nscore:" + score.ToString(), guiStyle);
        } else {
            GUI.Label(new Rect(0, 0, 200, 50), "score:" + score.ToString(), guiStyle);
        }
    }

player-gameover

これでゲームの完成です。

なんか足りない?

解説用に作成したものなのでゲームとしてはかなり物足りないです。例えば・・・

  • 音が無い
  • 画像が足りない
  • ハイスコアとかランキングとかない
  • 難易度が今ひとつ・・・

とかいろいろ考えれます。あとは自分で付け足してみてください。

追記

Unity でゲーム作ってる椿氏もFlappyBird的なゲーム作って作り方を公開しているのでリンクはっておきますね。めっちゃ参考になります。
テラシュールウェア [Unity]Flappy Birdライクなゲームを作成した際のメモ

Sponsored Link

シェアする

フォローする

コメント

  1. suesada より:

    全部書いてあるスクリプトを良かったら頂けないですか?