Google+ もご覧ください
ユーザーアイコン

Unityではじめるゲーム開発

Unityで玉転がしゲームを作ってみよう - その2

Nakamura001

Unityで玉転がしゲームを作ってみよう - その2

前回の記事から引き続きの内容と成っています。前回の記事が未読の方は先にそちらをご覧下さい。

コースを作ってみよう

現在の床は広すぎので難易度を上げる為に細い長い床に変更します。まずは「Floor」のSacleの値を(2, 1, 20)に変更します。続いて「Floor」を複製し、名前を「Floor2」に変更しInspectorのパラメータを以下の様に変更します。

  • Position(7.6, 0, 2.4)
  • Scale(15, 1, 4)

ここまでの作業をすると床はこの様なレイアウトに成っているはずです。

床のレイアウト
床のレイアウト

この状態でゲームを実行してみるとプレイヤー(球)が床から落ちた時にずっと落ち続けます。これでは一度ミスするともう遊べなくなってしまいます。

ある程度落下したらゲームをリセットしてもう一度チャレンジ出来るように変更しましょう。

実装方法としては簡単に済ませる場合にはプレイヤーのY座標の位置が一定の位置より小さくなったら(例えば -5.0 より小さい場合など)ゲームをリセットするというパターンがあります。

しかし、その様な実装の場合には上に(+Y方向に)長いステージを作った場合にはかなり落下し続けないとリトライ出来なく成ってしまいます。

今回は決められた時間落下し続けた場合にゲームをリセットする様にします。C#ファイルを「PlayerAction」という名前で作成し、以下の内容を記述します。

using UnityEngine;
using System.Collections;

public class PlayerAction : MonoBehaviour {
    Vector3 startPosition;
    float movePower = 80.0f;
    bool grounded = false;
    float lastGroundedTime;

    void Start () {
        startPosition = transform.position;
        lastGroundedTime = Time.time;
    }

    void OnCollisionStay(Collision collision) {
        grounded = true;
        lastGroundedTime = Time.time;
        rigidbody.freezeRotation = false;
    }

    void ResetGame() {
        transform.position = startPosition;
        transform.eulerAngles = Vector3.zero;
        rigidbody.velocity = Vector3.zero;
        rigidbody.freezeRotation = true;
    }

    void Update () {
        if (grounded) {
            var x = Input.GetAxis ("Horizontal") * Time.deltaTime * movePower;
            var z = Input.GetAxis ("Vertical") * Time.deltaTime * movePower;
            rigidbody.AddForce(x, 0, z);
        }

        if (Time.time - lastGroundedTime > 2.0f) {
            lastGroundedTime = Time.time;
            ResetGame();
        }

        float rayDistance = 20.0f;
        Debug.DrawRay(transform.position, -Vector3.up * rayDistance, Color.red);
        if (Physics.Raycast(transform.position, -Vector3.up, rayDistance)) {
            lastGroundedTime = Time.time;
        }
    }
}

基本的には決められた時間落下し続けたらゲームをリセットするという実装にしています。しかし、その様な実装にしておくと意図的にユーザが落下して移動のショートカットを試みた場合にも落下途中でゲームのリセットが発生してしまいます。

その様な状況が発生するのを避けるため、今回はPhysics.Raycast()を使ってプレイヤーから地面(-Y方向)に向かって Ray を飛ばし、他のオブジェクト(床)とぶつからないかチェックすることにします。この実装であれば、落下先に床がある場合にはゲームがリセットされないようになります。

        if (Physics.Raycast(transform.position, -Vector3.up, rayDistance)) {
            lastGroundedTime = Time.time;
        }

ここの記述では Ray を飛ばす距離の rayDistance には 20.0f を設定して有りますがこの値はステージの構成により調整が必要です。かなりの距離を落下した後に床が存在するようなステージ構成の場合にはもっと大きな値にする必要があります。当然ですがこの値を大きくすればするほど処理の負荷は増えるので無闇に大きな値にせず、適切な値を設定するようにしましょう。

今回のように Ray を飛ばして当たり判定をする場合には実際には画面には Ray が見えないので Debug.DrawRay() も合わせて記述しておくと Ray が適切に設定されているかが簡単に確認できるようになります。

Debug.DrawRay()Physics.Raycast()とは異なり、 Ray の距離(長さ)を指定する部分がありません。代わりに第2引数で指定したベクトルの向きとサイズが利用されます。そのため以下のように記述すれば Physics.Raycast() で指定しているのと同じ長さのラインが描画されます。

        Debug.DrawRay(transform.position, -Vector3.up * rayDistance, Color.red);

Debug.DrawRay()
Debug.DrawRay()

このラインはあくまでデバッグ用であるため、Sceneビューのみに表示され、 Game ビューには表示されません。そのため、ゲーム実行中に Scene ビューを見て Ray の状況を確認する必要があります。

ゲーム実行時に Game ビューがフルスクリーンになるように設定している方や Game ビューと Scene ビューを同じ領域でタブ化している方はご注意下さい。

カメラを追従させよう

カメラの追従を実装を進める前にプレイヤーが操作しやすい様にMain Cameraの位置や向きを変更しておきましょう。それぞれのパラメータを以下のように変更して下さい。

  • Position(0, 2.5, -10)
  • Rotation(32, 0, 0)

それでは改めてカメラの追従の話に進みます。まずはじめにカメラがプレイヤーを追従するにはどうすれば良いかを考えてみましょう。

すぐに思いつくのは一定の距離を保ったまま付いていくというパターンです。C#のプログラムで表現するとこのようになります。

using UnityEngine;
using System.Collections;

public class CameraControl : MonoBehaviour {
    public Transform target;
    Vector3 relativePosition;

    void Start () {
        relativePosition = transform.position - target.position;
    }

    void LateUpdate () {
        transform.position = target.position + relativePosition;
    }
}

このプログラムをCameraControlという名前のC#ファイルで作成し、上記のプログラムを貼り付けた後に Hierarchy ビューのMain Cameraにドラッグし、 Inpector の Target の項目に Hierarchy ビューから Player をドラッグして下さい。

CameraControl
CameraControl

処理としては Start() で現在のカメラとプレイヤーの位置関係(相対的な位置)を保存し、 Update() で毎回その相対位置を保つように更新する作りになっています。

作業が終わったらゲームを実行してみましょう。キーボードのカーソルを動かすとカメラが平行に追従しているのが確認できます。

もうちょっとこった実装だと常にPlayerの背後に位置する実装もありますがそちらの実装で進めるとPlayerの移動処理もそれに合わせた修正が必要になるため、今回はこちらのシンプルな実装で進めることにします。

今回はここまでです。ここまでの作業を行ったプロジェクトをこちらに置いておきます。もし、ここまでの作業が上手く行かなかった場合には記事とこのプロジェクトとを見比べながら確認してみて下さい。

次回はゴールの作成やモバイル環境での操作などを解説します。

Unity
タグ:

記事をリクエストする

関連記事

コメント