Developer

【Unity実践】#8 プロトタイプ編 ~ 箱の作成 part2 ~【Boxゲーム】
2021.01.06
Lv2

【Unity実践】#8 プロトタイプ編 ~ 箱の作成 part2 ~【Boxゲーム】

今回の内容

前回に続いて箱の作成となります。
箱を壊したときにプレイヤーが動き出す仕組みを実装します。

※初めての方はこちらから
【第1回記事】この連載について

PlayerScriptにメソッド追加

箱を壊したときにプレイヤーの移動を制御する処理を追加していきます。
準備として、PlayerScript にメソッドを追加しましょう。

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

public class PlayerScript : MonoBehaviour
{
    Animator charaAnim;

    public bool isMove;

    void Start()
    {
        charaAnim = GetComponent<Animator>();
    }

    void FixedUpdate()
    {
        if (isMove)
        {
            transform.position += transform.forward * 0.03f;
        }
    }

    void Update()
    {
        charaAnim.SetBool("isRunning", isMove);
    }

    private void OnCollisionStay(Collision collision)
    {
        switch (collision.gameObject.tag)
        {
            case "Wall":
                if (isMove) turn();
                break;
        }
    }

    // プレイヤーの向きを反転
    public void turn()
    {
        transform.Rotate(new Vector3(0, 180, 0));
    }

    // プレイヤーを左に向ける
    public void TurnLeft()
    {
        transform.rotation = Quaternion.Euler(0, -90, 0);
    }

    // プレイヤーを右に向ける
    public void TurnRight()
    {
        transform.rotation = Quaternion.Euler(0, 90, 0);
    }

    // 左に走る
    public void MoveLeft()
    {
        TurnLeft();
        isMove = true;
    }

    // 右に走る
    public void MoveRight()
    {
        TurnRight();
        isMove = true;
    }
}

各メソッドの内容はコメントおよびメソッド名の通りで、向きの変更と移動の開始処理をメソッド化しています。

BoxScriptによるプレイヤー制御

先ほど追加した Turn、Move 系のメソッドを BoxScript から呼び出せるようにします。
完成形がこちらです。

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

public class BoxScript : MonoBehaviour
{
    public enum PlayerMove { Default, MoveLeft, MoveRight }

    public PlayerMove playerMove;

    PlayerScript player;

    void Start()
    {
        player = GameObject.Find("Player").GetComponent<PlayerScript>();
    }

    public void onBoxClick()
    {
        // プレイヤーの移動を開始する
        switch (playerMove)
        {
            case PlayerMove.MoveLeft:
                PlayerMoveLeft();
                break;
            case PlayerMove.MoveRight:
                PlayerMoveRight();
                break;
        }

        Destroy(gameObject);
    }

    // 初期配置で右に移動させる場合に使う
    void PlayerMoveRight()
    {
        if (!player.isMove)
        {
            player.MoveRight();
        }
    }

    // 初期配置で左に移動させる場合に使う
    void PlayerMoveLeft()
    {
        if (!player.isMove)
        {
            player.MoveLeft();
        }
    }
}

やや複雑なのと、enum を使ったことが無い人は戸惑うかもしれないので解説していきます。
まず全体の流れをザックリ整理すると、以下の通りです。

全体の流れ
① 箱をクリック ⇒ onBoxClickメソッドが実行される
② BoxScript(Box_Wall) の playerMove の設定を判別
・MoveLeft が設定されている ⇒ PlayerScript の MoveLeft を実行
・MoveRight が設定されている ⇒ PlayerScript の MoveRight を実行
・Default が設定されている ⇒ プレイヤーに対しては何もしない

Box_Wall の設定によって、箱を壊したときにプレイヤーが右 or 左に移動開始するか、移動をしないかの制御ができるように実装しています。
これだけではまだピンと来ないかもしれないので、この後の個別の説明を見てから戻って読み返してみて下さい。

1つ目のブロック(7~16行目)
まず簡単な所として後半の11~16行目ですが、
プロパティとして PlayerScript型の変数を用意して、Startメソッド内で Playerオブジェクトから取得しています。
これは、後に onBoxClickメソッド、およびそれに紐づくメソッドからの参照をスムーズに行うための準備です。

初見だとやや難解なのが前半の7行目と9行目で、enum(列挙型)という仕組みを使っています。
これは簡単に言うと定数と配列を組み合わせたような仕組みで、
7行目では PlayerMoveグループ(型)を作成して、その子要素として「Default」「MoveLeft」「MoveRight」の3つを定義しています。

7行目でやっているのはあくまで「定義」に過ぎないので、使用するには9行目のように PlayerMove型の変数を用意して、3つの値のいずれかを設定して使用します。
public の変数として定義することで、以下の様にインスペクタービューから、プルダウンで選択ができるようになります。

今回のような、設定値を限定された複数の値の中から選びたい時に使用することが多いです。
詳しくは調べてみて下さい。

2つ目のブロック(20~29行目)
前回作成した onBoxClickメソッドに処理を追加しています。
1つめのブロックで作成したプロパティ「playerMove」の値が「PlayerMove.MoveLeft」もしくは「PlayerMove.MoveRight」であれば、
それぞれに対応する処理を実行しています。

3つ目のブロック(34~50行目)
「PlayerMoveRight」「PlayerMoveLeft」の2つのメソッドを追加しました。
それぞれ、PlayerScriptの「MoveRight」「MoveLeft」メソッドを呼び出すためのメソッドです。
細かいところとして、Playerの状態が「isMove」であるとき、すなわち既に移動を開始している時には、呼び出さないように実装しています。
この2つのメソッドが、2つ目のブロックの判定結果によって呼び出される流れとなっています。

やや長いので戸惑ったかもしれませんが、やっていること自体は比較的シンプルかなと思います。

動作確認

スクリプトが作成できたら、Box_Wall の BoxScript で「PlayerMove」を「MoveRight」に設定しましょう。

シーンを再生して、箱をクリックするとキャラが右に動き出せば成功です。

これで今までの様に、直接 Player の「isMove」を変更しなくても動くようになりました。
念のため「MoveLeft」にすると左に動き始めることも確認しておきましょう。

プレハブ化

最低限、箱の仕組みが出来上がったのでプレハブ化します。
プレハブ化したら、「Player Move」を「Default」に戻しましょう。(プロジェクトビュー側のBox_Wallです。)

ここでもう1つ、水平に置くための箱を別でプレハブ化します。
と言うのも、Box_Wall には「Wall」タグが付いているので、
このまま水平に配置すると、キャラクターが反転をしてしまいます。

なのでほぼ同じ機能なのですが、タグの有無だけを変えたプレハブを作成します。
Box_Wall を複製(Ctrl + D)して名前を「Box」に変えて、

タグを「Untagged」、z軸周りに90度回転させればOKです。

↓こんな感じになるようにシーンに配置しましょう。

この Box の playerMove の値は「Default」にしておきます。

↓設定値

シーンを再生して、水平なBox上をプレイヤーが移動できていればOKです。

おわりに

ここまでで一旦、箱の作成は完了です。
プレイヤーと同様にまた随時、調整を入れることはあります。
次回からは、クリアやゲームオーバーと言った、シーン制御の仕組みを実装していきます!

 
 

連載目次リンク

実践Unityゲームプログラミング 連載目次
 

関連する連載リンク

「初心者のための」Unityゲーム制作 目次
 

© Unity Technologies Japan/UCL