Unityでゲームを作ろう:第2回「プレイヤーを動かすスクリプトを書こう」

Unity

こんにちは、トナカイです。

ゲームを作ろうシリーズ第2回です。

前回はフィールドに当たり判定を付ける所まで進めました。

第2回では、キャラクターを操作できるようにUnityでスクリプトを書いていきます。

この記事では、以下の内容について解説します。

  • キーボードでキャラクターを動かすスクリプトの書き方
  • プレイヤーへの当たり判定の付け方

プレイヤーのインポート

今回作るゲームでは、プレイヤーを操作してフィールドを歩けるようにします。

説明用に、トナカイが過去に作成したキャラクターを使っています。

自分でもこの記事の内容を試す場合には、「ユニティちゃん」など、アニメーション付きの配布モデルをお使いいただけると良いのではと思います。

UnityのProjectにインポートしたプレイヤーのオブジェクトを、Sceneにドラッグします。

大きすぎたので、Hierarchyのプレイヤーオブジェクトを選択してScaleを小さくしました。

スクリプトを書く

次に、プレイヤーを動かすスクリプトを書きます。

Unityでは、Projectにあるプラスマークからスクリプトを追加することができます。

プラスマークをクリックすると以下の画面が表示されるので、「C# Script」を選択してください。

追加されたスクリプトを選択すると、自動的にエディターが開かれます(Visual Studioを使っています)。

ここに、プレイヤーを動かすコードを書いていきます。

まずは、右矢印キーを押しているときにプレイヤーが右に動くようにします。

ただ右に動かすだけでは、正面を向いたまま右に移動することになってしまうので、移動と同時に右を向く処理もつけます。

とりあえず、こんなスクリプトを書いてみてください。赤枠が追加したコードです。詳細の説明はこの後します。

コードの意味

このコードで行っているのは

  • プレイヤーの移動速度の設定
  • 矢印キーを押している間だけ移動するようにする
  • プレイヤーの向きが移動方向と同じになるように回転させる

の3つです。

プレイヤーの移動速度の設定

「int speed = 3;」で移動速度を設定しました。フィールドの大きさによって適切な速さは変わるので、いい感じになるように調整してください。

右矢印キーを押している間だけ移動するようにする

矢印キーを押している間だけ移動するようにする処理は、以下のコードが対応しています。

if(Input.GetKey("right") == true)

{

    transform.position += new Vector3(0, 0, speed * Time.deltaTime);

    transform.rotation = Quaternion.Euler(0,0,0);

}

「〇〇している間だけ動かす」という、ある条件が満たされている時だけ行う処理のため、if文を使いました。

if文とは

条件を満たしたときに、どんな処理をするか書くために使うコードです。

以下のような書き方をします。

if(条件){条件を満たしたら実行する処理};

Input.GetKey」は、キーが押されているかどうかを判断するコードです。

Input.GetKey(“right”)であれば、右矢印キーが押されている時にtrueの値を返します。

かっこの中に入れる文字によって、どのキーにするか選べます。

right右矢印キー
left左矢印キー
up上矢印キー
down下矢印キー

また、「==」は左と右の値が同じということを意味します。

そのため、if(Input.GetKey(“right”) == true)の意味は

「右矢印キーが押されている(true)ときは、かっこ内の処理を頑張るぞー!」

という感じになります。

Input.GetKey(“right”)がtrueのときに頑張ってもらう処理が、

transform.position += new Vector3(0, 0, speed * Time.deltaTime);

transform.rotation = Quaternion.Euler(0, 0, 0);

になります。

「transform」「Time.deltaTime」「new」「Vector3」「Quaternion.Euler」のそれぞれについて解説します。

transform

transformは、オブジェクトの位置や回転などの情報を扱えます。

参考:Transform – Unity スクリプトリファレンス (unity3d.com)

transform.positionの場合は位置を、transform.rotationの場合は回転についての情報を持っていることになります。

Time.deltaTime

Time.deltaTimeは、「直前のフレームから現在のフレームになるまでの経過時間(秒)」を表します。

参考:Time-deltaTime – Unity スクリプトリファレンス (unity3d.com)

※Unityにおけるフレームの意味については、こちらの記事が参考になります。トナカイが書いたものではありませんが、映画のフレームという馴染みやすいものから説明されており、分かりやすいです。

new

インスタンス作成という作業を行っています。

Vector3

オブジェクトの位置関係を表す時に使います。

Vector3(X座標, Y座標, Z座標)となっています。

ひとまずZ座標の方向(画面の右方向)に動かすため、Z座標の引数にのみ「speed * Time.deltaTime」を入れました。

以上をまとめると、

transform.position += new Vector3(0, 0, speed * Time.deltaTime);

では

「プレイヤーのオブジェクトの現在の位置に、プレイヤーの移動距離を足す」

という処理を行っているということになります。

Quaternion.Euler

Quaternion.Eulerで、プレイヤーの向きを指定しています。

Quaternion.Euler(X軸の回転, Y軸の回転, Z軸の回転)になります。

Unityの座標軸を見てみると、Y軸で回転することがわかります。

回転の方向については、右方向が0度に対応していたため、Quaternion.Euler(0, 0, 0)としました。

結果として

transform.rotation = Quaternion.Euler(0, 0, 0);

では、

「オブジェクト(キャラクター)の向きにXYZ軸0度の回転を代入する」

という処理を行うことになります。

スクリプトを実行する

ここまでできたら、Hierarchyにあるスクリプトを、Projectにあるプレイヤーオブジェクトにドラッグしてアタッチしてください。

この状態で再生し、右矢印キーを押すと動画のような動きをします。

なお、プレイヤーが壁をすり抜けてしまうのはRigidbodyとコライダーがついていないためです。この後の「プレイヤーに当たり判定を付ける」ですり抜けないように設定します。

右矢印だけではなく、他の矢印キーを押したときにも動くように、コードを追加しました。コードはこれで完成です。

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

public class PlayerController : MonoBehaviour
{
    int speed = 3;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKey("right") == true)
        {
            transform.position += new Vector3(0, 0, speed * Time.deltaTime);
            transform.rotation = Quaternion.Euler(0, 0, 0);
        }
        if (Input.GetKey("left") == true)
        {
            transform.position -= new Vector3(0, 0, speed * Time.deltaTime);
            transform.rotation = Quaternion.Euler(0 , 180, 0);
        }
        if (Input.GetKey("up") == true)
        {
            transform.position -= new Vector3(speed * Time.deltaTime, 0, 0);
            transform.rotation = Quaternion.Euler(0, 270, 0);
        }
        if (Input.GetKey("down") == true)
        {
            transform.position += new Vector3(speed * Time.deltaTime, 0, 0);
            transform.rotation = Quaternion.Euler(0, 90, 0);
        }
    }
}

プレイヤーに当たり判定を付ける

このままだとプレイヤーが壁をすり抜けてしまいます。当たり判定を付けるために、プレイヤーオブジェクトのコンポネントにRigidbodyとコライダーを追加します。

Rigidbodyの追加方法

プレイヤーオブジェクトのInspectorにある「Add Component」から「Physics」へと進み、Rigidbodyを選択すれば完了です。

コライダーの追加方法

「コライダーってなんだろう?」という場合は、前回の記事「Unityでゲームを作ろう:第1回「ゲームフィールドを作成して当たり判定を付ける」」をご覧ください。

ゲームのフィールドにはメッシュコライダーを使いましたが、Unityマニュアルによれば「メッシュコライダーは処理が重くなりやすいので使うのは控えめにしてね!」とのことです。

参考:Mesh Collider – Unity マニュアル (unity3d.com)

プレイヤーのオブジェクトは複雑な形をしていないため、別のコライダーを使おうと思います。

ここではBox Colliderを使うことにしました。

前回同様、「Add Component」からBox Colliderを選択します。

コライダーを追加しただけではプレイヤーと当たり判定の大きさが合わないため、大きさを調節します。

InspectorにあるEdit Colliderの横にあるマークをクリックすると、コライダーの大きさを編集できるようになります。

前や横から見て、プレイヤーの大きさと合うようにしました。

まとめ

ここまで進めると、以下の動画の通りになります。

今回は、プレイヤーをキーボードで動かせるようにコードを書きました。

次回は、歩行モーションの追加と、カメラがキャラクターを追いかける仕組みを実装します。