【Unity】イベントでゲームの進行管理をする #2

投稿者: | 2020-11-27

イベントでゲームの進行を管理するの方法で一連の進行を作ってみました。

アイテムを置く場所にCubeを置いて、空のオブジェクトの子にし、MeshRendererをオフにしておきました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using UnityEngine.SceneManagement;

public class GameScript5 : MonoBehaviour
{
    Action updateAction;

    public delegate void PickItemEventHandler(ItemScript2 item);
    public event PickItemEventHandler pickItem;

    public delegate void PlayerCollideEventHandler(GameObject item);
    public event PlayerCollideEventHandler playerCollide;

    public delegate void FixMachineEventHandler();
    public event FixMachineEventHandler fixMachine;

    int itemCount; // 拾ったアイテムの数
    float sec; // 時間

    [SerializeField] Text text;
    [SerializeField] Text text2;
    [SerializeField] MeshRenderer planeMeshRenderer; // 床
    [SerializeField] Material[] materials;
    [SerializeField] GameObject redCollider; // 赤いコライダー
    [SerializeField] GameObject greenCollider; // 緑のコライダー
    [SerializeField] GameObject machine; // 機械のプレハブ
    [SerializeField] GameObject item; // アイテムのプレハブ
    [SerializeField] Transform points; // アイテム等を置く位置のルート
    
    // Start is called before the first frame update
    void Start()
    {
        // コライダーを非アクティブにする
        redCollider.SetActive(false); 
        greenCollider.SetActive(false);
        text2.text = "よーい";
        updateAction = UpdateAction1; // 1つ目のメソッドを入れる
    }

    // Update is called once per frame
    void Update()
    {
        if(updateAction != null) updateAction();
    }

    // 開始前のカウント
    void UpdateAction1()
    {
        sec += Time.deltaTime;
        
        if (sec >= 3f)
        {
            text2.text = "スタート";
            text.text = "制限時間内にアイテムを5個拾う";
            pickItem = PickItem1;        
            sec = 0f;
            updateAction = UpdateAction2;

            // アイテムを生成
            for (int n = 0; n < points.childCount-1;n++)
            {
                Instantiate(item, points.GetChild(n).position, points.GetChild(n).rotation);
            }
        }
    }

    // 1秒待つ
    void UpdateAction2()
    {
        sec += Time.deltaTime;
        if (sec >= 1f)
        {
            sec = 5f;
            updateAction = UpdateAction3;

        }
    }

    // カウントダウン
    void UpdateAction3()
    {
        sec -= Time.deltaTime;

        text2.text = sec + "";

        // タイムアップ
        if (sec <= 0f)
        {
            pickItem = null;
            text2.text = "";
            // 床を消す
            planeMeshRenderer.gameObject.SetActive(false);
            updateAction = UpdateAction4;
        }
    }

    // 3秒後にシーンを読み込み
    void UpdateAction4()
    {
        sec += Time.deltaTime;

        // 3秒後に再スタート
        if (sec >= 3f)
        {
            sec = 0f;
            SceneManager.LoadScene("New Scene");
        }

    }

    // アイテム取得のイベントを実行
    public void PickItem(ItemScript2 item)
    {
        if (pickItem != null) pickItem(item);
    }

    // アイテム取得
    void PickItem1(ItemScript2 item)
    {
        itemCount++;

        // 5個拾った時
        if(itemCount >= 5f)
        {
            sec = 0f;
            text2.text = "";
            updateAction = null; // カウントダウンを終了
            pickItem = null; // アイテム取得時に何もしないようにする
            playerCollide = PlayerCollide1; // プレイヤー衝突メソッド
            redCollider.SetActive(true); // コライダーをアクティブ
            greenCollider.SetActive(true);
            text.text = "赤いコライダーに入る";
        }
    }

    // トリガーコライダー入ったときのイベント実行
    public void PlayerCollide(GameObject obj)
    {
        if(playerCollide != null) playerCollide(obj);
    }

    // トリガーエンター
    void PlayerCollide1(GameObject obj)
    {
        // 赤いコライダーに入ったら
        if (obj.name == "RedCollider")
        {
            Destroy(obj); // 赤いコライダーを破壊
            playerCollide = null; // 空にする

            // 機械を生成
            Instantiate(machine, points.GetChild(12).position, points.GetChild(12).rotation); 

            text.text = "機械を修理する";
            fixMachine = FixMachine1; // 機械の修理完了時のメソッド入れる

        }
        // 緑のコライダーに入ったら
        else if (obj.name == "GreenCollider")
        {
            playerCollide = null;

            // 床を消す
            planeMeshRenderer.gameObject.SetActive(false);
            text2.text = "";
            updateAction = UpdateAction4;
        }
    }

    // 修理完了時のイベント実行
    public void FixMachine()
    {

        if (fixMachine != null) fixMachine();
    }

    // 修理完了
    void FixMachine1()
    {
        text.text = "";
        text2.text = "終了";
        fixMachine = null;
        sec = 0f;
        updateAction = UpdateAction4;
    }

}

進行管理のスクリプトでは、アイテム取得やコライダーに入ったときのイベントは空のままにしておいて、Update()で呼ぶデリゲートに1つ目のメソッドを入れています。

void Start()
{
    // コライダーを非アクティブにする
    redCollider.SetActive(false); 
    greenCollider.SetActive(false);
    text2.text = "よーい";
    updateAction = UpdateAction1; // 1つ目のメソッドを入れる
}

// Update is called once per frame
void Update()
{
    if(updateAction != null) updateAction();
}

1つ目のメソッドでは、時間を計って3秒後にスタートし、指示のテキストを表示します。アイテム取得のイベントにメソッドを入れて、繰り返し処理でアイテムを生成します。

// 開始前のカウント
void UpdateAction1()
{
    sec += Time.deltaTime;
        
    if (sec >= 3f)
    {
        text2.text = "スタート";
        text.text = "制限時間内にアイテムを5個拾う";
        pickItem = PickItem1;        
        sec = 0f;
        updateAction = UpdateAction2;

        // アイテムを生成
        for (int n = 0; n < points.childCount-1;n++)
        {
            Instantiate(item, points.GetChild(n).position, points.GetChild(n).rotation);
        }
    }
}

そして、Updateのデリゲートに2つ目のメソッドを入れています。このメソッドでは「スタート」の表示を少しの間残したいので1秒待って3つ目のメソッドに変えるだけです。

// 1秒待つ
void UpdateAction2()
{
    sec += Time.deltaTime;
    if (sec >= 1f)
    {
        sec = 5f;
        updateAction = UpdateAction3;

    }
}

3つ目では、5秒間カウントダウンして0になるとアイテム取得時のイベントを空にし、床を消して、4つ目のメソッドに変えます。

// カウントダウン
void UpdateAction3()
{
    sec -= Time.deltaTime;

    text2.text = sec + "";

    // タイムアップ
    if (sec <= 0f)
    {
        pickItem = null;
        text2.text = "";
        // 床を消す
        planeMeshRenderer.gameObject.SetActive(false);
        updateAction = UpdateAction4;
    }
}

4つ目では3秒後にシーンを読み込むだけなので、タイムアップでゲームオーバーになります。

// 3秒後にシーンを読み込み
void UpdateAction4()
{
    sec += Time.deltaTime;

    // 3秒後に再スタート
    if (sec >= 3f)
    {
        sec = 0f;
        SceneManager.LoadScene("New Scene");
    }

}

タイムアップになるまではアイテム取得時のイベントにメソッドが入っています。ここでは拾ったアイテムの数をカウントしていき、5個になると、Update()のデリゲートとアイテム取得のイベントを空にし、コライダーに衝突したときのイベントにメソッドをいれて、コライダーをアクティブにします。指示のテキストも変更します。

// アイテム取得のイベントを実行
public void PickItem(ItemScript2 item)
{
    if (pickItem != null) pickItem(item);
}

// アイテム取得
void PickItem1(ItemScript2 item)
{
    itemCount++;

    // 5個拾った時
    if(itemCount >= 5f)
    {
        sec = 0f;
        text2.text = "";
        updateAction = null; // カウントダウンを終了
        pickItem = null; // アイテム取得時に何もしないようにする
        playerCollide = PlayerCollide1; // プレイヤー衝突メソッド
        redCollider.SetActive(true); // コライダーをアクティブ
        greenCollider.SetActive(true);
        text.text = "赤いコライダーに入る";
    }
}

赤いコライダーに入ると機械を生成し、指示のテキストを変えます。修理完了のイベントにメソッドをいれます。

緑のコライダーに入ると、タイムアップのときと同様にゲームオーバーになります。

// トリガーコライダー入ったときのイベント実行
public void PlayerCollide(GameObject obj)
{
    if(playerCollide != null) playerCollide(obj);
}

// トリガーエンター
void PlayerCollide1(GameObject obj)
{
    // 赤いコライダーに入ったら
    if (obj.name == "RedCollider")
    {
        Destroy(obj); // 赤いコライダーを破壊
        playerCollide = null; // 空にする

        // 機械を生成
        Instantiate(machine, points.GetChild(12).position, points.GetChild(12).rotation); 

        text.text = "機械を修理する";
        fixMachine = FixMachine1; // 機械の修理完了時のメソッド入れる

    }
    // 緑のコライダーに入ったら
    else if (obj.name == "GreenCollider")
    {
        playerCollide = null;

        // 床を消す
        planeMeshRenderer.gameObject.SetActive(false);
        text2.text = "";
        updateAction = UpdateAction4;
    }
}

長押し中に作動させて進行度をゲージに表示するの方法で機械のゲージが満タンになると修理完了のイベントが呼ばれて、ゲームが終了し3秒後にシーンを読み込みます。

// 修理完了時のイベント実行
public void FixMachine()
{

    if (fixMachine != null) fixMachine();
}

// 修理完了
void FixMachine1()
{
    text.text = "";
    text2.text = "終了";
    fixMachine = null;
    sec = 0f;
    updateAction = UpdateAction4;
}

コメントを残す

メールアドレスが公開されることはありません。