初心者でもできる! 7日間で作るUnityゲーム開発

Day4:タイムトライアル機能を追加する!

この記事を読むのに必要な時間:およそ 5 分

タイムトライアル機能を追加してゲーム性を強化

前回の記事では,爆発エフェクトと爆発音を追加したことによってゲームの臨場感が増しました。臨場感は増しましたが,弾が当たったら爆発するだけではゲーム性がありません。そこで今回はタイムトライアル機能を追加してゲーム性を強化していきたいと思います。

不要なラベル表示を消す

現状ゲームを実行すると,画面左上に白い文字で

Try to kill the bear!
Use Fire1 to shoot bullets
Use Fire2 to toggle aiming with bazooka

と表示されます。

クマを殺せ!
Fire1ボタンで弾を撃て
Fire2ボタンでバズーカを構えろ

という意味の英語です。不要なので削除します。

さて,これらの文字はどのコードで表示しているのでしょうか? 自分が書いたコードなら,どこで何をやっているかがわかりますが,アセットストアのアセットのように他人が書いたコードの場合,どうすればよいでしょうか?

私ならこういう場合,IDEの検索機能を使います。MonoDevelopのメニュー[Search]ー[Find in Files]をクリックします。表示されたダイアログの「Find:」「Try to kill the bear」を入力して[Find]ボタンをクリックします。すると,Bazooka.csのコードが検索にヒットするので対象のコードを発見することができます。

このように,対象の処理をどこでやっているか分からない時にはIDEでソースコードを検索することをおすすめします。

Bazooka.csの以下の部分でラベル表示しているので,このコードを削除しましょう。

    void OnGUI()
    {
        GUILayout.Label("Try to kill the bear!");
        GUILayout.Label("Use Fire1 to shoot bullets");
        GUILayout.Label("Use Fire2 to toggle aiming with bazooka");
    }

Unityの標準UI機能では,OnGUIというメソッドの中にラベルやボタンなどのUIを表示するコードを書くルールになっています。

GUILayout.Labelメソッドの引数にラベル表示したい文字列を渡すと画面にラベルが表示される仕組みとなっています。

スコアカウント処理を追加する

GameControl.csのGameControlクラスに以下のフィールドを追加します。

    int score = 0;

続けて以下のコードを追加します。

    public void AddScore() {
        score++;
    }

    bool FinishedGame() {
        return GameObject.FindWithTag("Teddy") == null;
    }

AddScoreメソッドではフィールド定義したscoreを1加算しています。

FinishedGameメソッドはゲームが終了したかの判定をしています。GameObject.FindWithTag("Teddy") == null;でTeddyタグの付いているオブジェクトが一つもない場合trueを返しています。つまり,クマをすべて打ち終わったらゲーム終了という判定になります。

続いて,Bear.csのBearクラスのOnCollisionEnterメソッドを以下のように編集します。コメント行「今回追加」以下の2行を追加してください。

    void OnCollisionEnter(Collision collision) {
        if (avatar != null) {
            if (hitFlag == false && collision.collider.tag == "Bullet") {
                hitFlag = true;
                GameObject exp = (GameObject)Instantiate(detonator.gameObject, transform.position, Quaternion.identity);

                //今回追加
                var gameCotroll = GameObject.Find("GameControl");
                gameCotroll.transform.GetComponent<GameControl>().AddScore();
                
                var currentState = avatar.GetCurrentAnimatorStateInfo(0);
                var nextState = avatar.GetNextAnimatorStateInfo(0);
                if (!currentState.IsName("Base Layer.Dying") && !nextState.IsName("Base Layer.Dying")) {
                    avatar.SetBool("Dying", true);
                    Destroy(this.gameObject, 3.0f);
                }
            }
        }
    }

OnCollisionEnterはクマが何かと接触した際に呼び出されるメソッドです。今回追加した2行で,弾と接触時にGameControlのAddScoreメソッド呼び出しをしています。

var gameCotroll = GameObject.Find("GameControl");でHierarchyのGameControlオブジェクトを取得して,取得したGameControlにアタッチされているGameControlスクリプトをgameCotroll.transform.GetComponent<GameControl>().AddScore();で取得してAddScoreメソッドを呼び出しています。

タイム測定処理を追加する

GameControlクラスに以下のフィールドを追加します。

    float elapsedTime;

続けてUpdateメソッドを以下のように編集します。

    void Update () {
        if (!FinishedGame()) {
            elapsedTime += Time.deltaTime;
        }
    }

Updateメソッドは毎フレームごとに呼び出されるメソッドです。フレームとは画面を描画する単位です。fps(frame per second)という単位があって,1秒間に何回画面を描画するかを表します。30fpsだったら1秒間に30回描画処理が走るので,Updateメソッドは1秒間に30回呼び出されることになります。なので,Updateメソッドは1秒間にたくさん呼び出されるものだと覚えておいてください。そのため,Updateメソッドの中に重い処理を書くとゲームの動作が重たくなってしまうので,そうならないよう注意しましょう!

今回追加したコードはif (!FinishedGame()) {でゲームが終了していない場合,elapsedTime += Time.deltaTime;で経過時間を加算しています。Time.deltaTime;は前のフレームから現在のフレームまでに経過した時間を返します。これをUpdateメソッドの中で毎回加算していくことで,ゲーム内での経過時間を計測しています。

著者プロフィール

やまろう

フリーランスITエンジニア。

業務系SIerに10数年勤務後独立。現在はUnityでスマートフォンのネイティブゲーム開発に従事。仕事の傍ら,個人でフリーゲームを開発している。

URL: http://mikumikuplay.com/

ニコニコ生放送にてプログラミングに関する生放送を配信中。
http://com.nicovideo.jp/community/co2268886

コメント

  • クリア

    スコアが10になっているのにクリア表記がでてきません。
    どうすればよいのでしょうか?バージョンはUNITY5です。

    Commented : #1  unity user (2017/09/17, 13:58)

コメントの記入