Google恐竜ゲーム風のランニングゲーム作成。Part3.ゲームオーバーとリセット【Unityゲーム作成】

UnityでGoogle恐竜ゲーム風味のゲーム制作、第3回目です。今回は当たり判定を追加して、ゲームオーバーとリセットを作成していきます。

はじめに

今回は第3回目です。第1回目は下記から。

今回やる事

パート3の今回は障害物に当たり判定を追加して、ゲームオーバーとリセットを作成します。

製作開始

では、前回の続きからです。

当たり判定の追加

まずは当たり判定の追加。

前回追加した障害物にリジッドボディ(Rigidbody)を追加して、コライダーのトリガーにするにチェックを入れます。

とりあえずは、プレイヤーが障害物にぶつかったら止まるようにしてみます。

Player.csの最後に下記の関数をとりあえず追加。

    private void OnTriggerEnter(Collider other)
    {
        _velocity = new Vector3(0, 0, 0);
    }

スタートメニュー・ゲーム終了(リセット)

ゲーム開始画面と、ゲーム終了画面を簡単に作成していきます。

UIからパネルを追加。名前をFinishにしておきます。

Finshパネルの配下にUIの「テキスト」と「ボタン」を追加。

ボタンのサイズ、テキストの内容、サイズなどを適当に調整しておきます。

「ゲーム」タブで下記の様な感じになっていればOK。

同じようにメニューパネルも作成。こっちは配下にボタンだけ。

下記の様な感じになっていればOK。

開始画面、終了画面と言うよりは、開始メッセージ、終了メッセージみたいな感じですかね。

作成したら両方とも初期状態は無効にしておきます。

状態遷移

ここからは、状態を管理して動作を制御していきます。

流れとしては、起動したら「メニューパネル」表示、スタートボタンを押したら「ゲームスタート」、ゲームスタートでプレイヤーが進むようにします。GameManagerスクリプトを下記に変更。

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

public class GameManager : MonoBehaviour
{
    public List<GameObject> ground;
    public GameObject player;

    public GameObject panelMenu;

    private float _spawnpoint = 10;
    private GameObject _ground;

    public static GameManager instance { get; private set; }
    public enum Status { MENU, INIT, GAME, FINISH }
    public Status statusMode;

    void Start()
    {
        instance = this;
        ChangeStatus(Status.MENU);
    }
    void Update()
    {
        if (player.transform.position.x > _spawnpoint - 20)
        {
            _ground = ground[Random.Range(0, ground.Count)];
            Instantiate(_ground, new Vector3(_spawnpoint, 0, 0), Quaternion.identity);
            _spawnpoint += 10;
        }

    }
    public void ChangeStatus(Status nextstatus)
    {
        switch (nextstatus)
        {
            case Status.MENU:
                panelMenu.SetActive(true);
                break;
            case Status.INIT:
                break;
            case Status.GAME:
                GameObject.Find("Capsule").GetComponent<Player>().enabled = true;
                GameObject.Find("Capsule").GetComponent<Player>().PlayerRun(5.0f);
                break;
            case Status.FINISH:
                break;
        }
    }
    public void StartClick()
    {
        panelMenu.SetActive(false);
        ChangeStatus(Status.GAME);
    }
}

Playerスクリプトは下記の様に変更。

障害物に当たったらスクリプトを無効にして終了状態に。後は細かいところを少し修正。

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

public class Player : MonoBehaviour
{
    [SerializeField] float _jump = 15f;
    private CharacterController _characterController;
    private Vector3 _velocity;

    private Transform _transform;
    private float _gravity = -30f;

    private float _skinWidth;
    private bool _isGround = true;

    void Start()
    {
        _characterController = GetComponent<CharacterController>();
        _transform = GetComponent<Transform>();
        _skinWidth = _characterController.skinWidth;

    }

    void Update()
    {
        if (_transform.position.y <= 1.5f + _skinWidth)
        {
            _velocity.y = 0;
            _isGround = true;
        }
        else
        {
            _velocity.y += _gravity * Time.deltaTime;
            _isGround = false;
        }

        if (Input.GetKeyDown(KeyCode.Space) && _isGround) 
        {
            _velocity.y += _jump;
        }

        _characterController.Move(_velocity * Time.deltaTime);
    }
    public void PlayerRun(float speed)
    {
            _velocity.x = speed;
    }
    private void OnTriggerEnter(Collider other)
    {
        GetComponent<Player>().enabled = false;
        GameManager.instance.ChangeStatus(GameManager.Status.FINISH);
    }
}

最終的なGameManagerスクリプトは下記の様な感じ。

ゲームオーバーでリスタートするとき、プレイヤーの位置を初期位置に戻して再スタート。かなりやっつけ感があって結構直すポイントも多いです。

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

public class GameManager : MonoBehaviour
{
    public List<GameObject> ground;
    public GameObject player;

    public GameObject panelFinish;
    public GameObject panelMenu;

    private float _spawnpoint = 10;
    private GameObject _ground;

    public static GameManager instance { get; private set; }
    public enum Status { MENU, INIT, GAME, FINISH }
    public Status statusMode;

    void Start()
    {
        instance = this;
        ChangeStatus(Status.MENU);
    }
    void Update()
    {
        if (player.transform.position.x > _spawnpoint - 20)
        {
            _ground = ground[Random.Range(0, ground.Count)];
            Instantiate(_ground, new Vector3(_spawnpoint, 0, 0), Quaternion.identity);
            _spawnpoint += 10;
        }

    }
    public void ChangeStatus(Status nextstatus)
    {
        switch (nextstatus)
        {
            case Status.MENU:
                panelMenu.SetActive(true);
                break;
            case Status.INIT:
                player.transform.position = new Vector3(0, 1.5f, 0);
                Invoke("ChangeGameMode", 1.5f);
                break;
            case Status.GAME:
                GameObject.Find("Capsule").GetComponent<Player>().enabled = true;
                GameObject.Find("Capsule").GetComponent<Player>().PlayerRun(5.0f);
                break;
            case Status.FINISH:
                panelFinish.SetActive(true);
                break;
        }
    }
    private void ChangeGameMode()
    {
        ChangeStatus(Status.GAME);
    }

    public void StartClick()
    {
        panelMenu.SetActive(false);
        ChangeStatus(Status.GAME);
    }
    public void ReStartClick()
    {
        panelFinish.SetActive(false);
        ChangeStatus(Status.INIT);
    }
}

あとは、メニューボタン、終了ボタンのクリック時に関数が実行されるようにすればOK

とりあえず、これで一通り動くように。

実際にはここから「スコア表示」や「スピード変化」、「オブジェクトの画像差し替え」、「アニメーション追加」などなどやることは沢山あります。もちろん、色々と追加した後にスクリプトの見直しも必要ですな。

まあ、一通り動いたので、この続きのPart4はやるかもしれないし、やらないかもしれないです(笑)

タイトルとURLをコピーしました