SG-落下するフルーツをランダムにするpart08

ここからは、ゲームとしてしっかり動くようにカスタマイズを行います。今回はフルーツをランダムに生成しますが、のちの予告表示と連動させるための準備も兼ねます。

目次

落下させるフルーツをランダムにする

フルーツをランダムに落下させるには今後のシステムを考慮して作るので、少し手間をはさみます。

RandomFruitsSelector

まずはランダムなフルーツを選択するプログラムを作成します。プレファブを返すことで、FruitsDropperと連携をすることが出来ます。実装したい内容は以下

  • 登場させたいフルーツをインスペクターでセット
  • Popメソッドで次に出すべきプレファブを返す
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RandomFruitsSelector : MonoBehaviour
{
    [SerializeField] private Fruits[] fruitsPrefabs;

    private Fruits reservedFruits;
    public Fruits ReservedFruits
    {
        get { return reservedFruits; }
    }

    private void Start()
    {
        Pop();
    }

    public Fruits Pop()
    {
        Fruits ret = reservedFruits;

        int index = Random.Range(0, fruitsPrefabs.Length);
        reservedFruits = fruitsPrefabs[index];

        return ret;
    }
}

UIに反映させるための処理はこのあとイベントを仕込むことで対応します。

FruitsDropperへの変更

作成済みのフルーツを落下させるやつは、事前にインスペクターで仕込んだフルーツ(さくらんぼ)しか落とすことが出来ませんでした。今回の変更で、次に出すべきフルーツを教えてもらいましょう。

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

public class FruitsDropper : MonoBehaviour
{
    [SerializeField] private RandomFruitsSelector randomFruitsSelector;
    public float moveSpeed = 5f;

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            var fruitsPrefab = randomFruitsSelector.Pop();
            Instantiate(fruitsPrefab, transform.position, Quaternion.identity);
        }

        float horizontal = Input.GetAxisRaw("Horizontal") * moveSpeed * Time.deltaTime;
        float x = Mathf.Clamp(transform.position.x + horizontal, -2.5f, 2.5f);
        transform.position = new Vector3(x, transform.position.y, transform.position.z);
    }
}

fruitsPrefabがメンバー変数からローカル変数になっているので注意してください。

ランダムにフルーツが降ってくるように設定

スクリプトの更新が出来たら、ゲームに反映してみましょう。

RandomFruitsSelectorをセット

まずはこっちのセットが先

  • スクリプトをアタッチ
    • 空のGameObjectを作成
    • 名前変更:RandomFruitsSelector
    • RandomFrutitsSelectorスクリプトをアタッチ
  • インスペクターにランダムに出現させたいフルーツのプレファブをセットする
    • 下図は4種類のフルーツをセット
    • 空欄が出ないようにしてください

FruitsDropperの設定

インスペクターの設定を変更します。といっても先程追加したゲームオブジェクトをセットするだけ。元々あったフルーツのプレファブはなくなりました。

動かして確認

ちゃんと実装出来ていれば同じ様にゲームを動かしてみると、設定したフルーツがランダムに投下されます。

Dropperの仕上げ

ここまでは実装主体で作成していたため、本来の動きと異なる挙動になっています。実際には次のような仕様が必要

  • 一定時間経過でドロップできるフルーツがぶら下がる
  • アクションボタンでくっついているフルーツをドロップ
  • 以上を繰り返し

ぶら下がっている状態を作る

まずはフルーツがぶら下がっている状態を作りたいと思います。ゲームが始まって、一定時間経過後にフルーツが自動でぶら下がるようにします。


public class FruitsDropper : MonoBehaviour
{
    [SerializeField] private RandomFruitsSelector randomFruitsSelector;
    public float moveSpeed = 5f;

    [SerializeField] private float coolTime = 1f;
    private Fruits fruitsInstance;

    private void Start()
    {
        StartCoroutine(HandleFruits(coolTime));
    }

    private IEnumerator HandleFruits(float delay)
    {
        yield return new WaitForSeconds(delay);
        var fruitsPrefab = randomFruitsSelector.Pop();
        fruitsInstance = Instantiate(fruitsPrefab, transform.position, Quaternion.identity, transform);
        fruitsInstance.GetComponent<Rigidbody2D>().isKinematic = true;
    }

    // Updateメソッドは省略
}

今回はKinematicを有効にすることで物理的な挙動を自動的に行わせないようにします。(自由落下とか)

掴んでいるフルーツを落下&次のフルーツをセット

あとはスペースキーを押してフルーツを落下できるようにしましょう。追加する内容として、セットされていないとフルーツを落とせないようにします。

ここではスクリプトをいったん全部載せます。

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

public class FruitsDropper : MonoBehaviour
{
    [SerializeField] private RandomFruitsSelector randomFruitsSelector;
    public float moveSpeed = 5f;

    [SerializeField] private float coolTime = 1f;
    private Fruits fruitsInstance;

    private void Start()
    {
        StartCoroutine(HandleFruits(coolTime));
    }

    private IEnumerator HandleFruits(float delay)
    {
        yield return new WaitForSeconds(delay);
        var fruitsPrefab = randomFruitsSelector.Pop();
        fruitsInstance = Instantiate(fruitsPrefab, transform.position, Quaternion.identity);
        fruitsInstance.transform.SetParent(transform);
        fruitsInstance.GetComponent<Rigidbody2D>().isKinematic = true;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space) && fruitsInstance != null)
        {
            fruitsInstance.GetComponent<Rigidbody2D>().isKinematic = false;
            fruitsInstance.transform.SetParent(null);
            fruitsInstance = null;
            StartCoroutine(HandleFruits(coolTime));
        }

        float horizontal = Input.GetAxisRaw("Horizontal") * moveSpeed * Time.deltaTime;
        float x = Mathf.Clamp(transform.position.x + horizontal, -2.5f, 2.5f);
        transform.position = new Vector3(x, transform.position.y, transform.position.z);
    }
}

次のフルーツが装填されるまでの時間は1秒になっていると思いますが、インスペクタでCoolTimeを変更することで帰ることが出来ます。

動かして確認

これでだいぶゲームっぽくなってきましたね。

何を落とすかがわかっただけでは不十分!次回はこの次に何を落とすことになるかの予告を実装したいと思います。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次