【Unity】2Dシューティングを作る ~ウェーブの仕組みを作成~

unity

プレイするゲームがないなら、自分で作ればいいじゃない!

ということで Unity 初心者が「ゲームを作る」ゲームをやっていきます!

今回は「敵をウェーブシステムで生成してみた」の記事です

 

スポンサーリンク

内容

ウェーブ(敵やイベント等の情報の塊)を用意して

ウェーブを管理するシステムを作成する

 

前回のランダム生成から…

ランダム任せは難しい・・・ということで

巷で「ウェーブ」と呼ばれるものを作ってみる!

 

やりたいこと

  • エディタで敵の配置、設定を行う
  • 小分けにできるようにして確認しやすいように
  • 敵だけでなく色々なものを設定したい

 

ウェーブオブジェクトクラス

ウェーブに組み込みたいオブジェクトはこのクラスを継承させる

public class WaveObj : MonoBehaviour
{
    enum END_TYPE
    {
        NONE = 0,
        EXISTENCE,  // 存在していたらウェーブ終了にならない
    }

    [SerializeField] END_TYPE endType = END_TYPE.NONE;

    // ウェーブを終了していいか
    public bool IsEnd()
    {
        if (endType == END_TYPE.EXISTENCE)
        {
            if (gameObject) { return false; }
        }

        return true;
    }
}

IsEnd

true にならないと次のウェーブに進まない

今回は敵を倒さないと次に進めないようにするために使用

 

ウェーブクラス

WaveObj クラスと生成時間を管理するクラス

時間になると設定した WaveObj をアクティブ状態にする

public class Wave : MonoBehaviour
{
    [System.Serializable]
    struct ObjData
    {
        public int generateFrame;
        public WaveObj waveObj;
    }

    [SerializeField] List<ObjData> objList;     // オブジェクトリスト
    int nowObj = 0;                             // 今のオブジェクト

    int frame = 0;
    bool waveEnd = false;

    void Start()
    {
        // 全てのオブジェクトを無効にする
        for (int i = 0; i < objList.Count; ++i)
        {
            if (objList[i].waveObj)
            {
                objList[i].waveObj.gameObject.SetActive(false);
            }
        }
    }

    void Update()
    {
        if (objList.Count <= 0 || waveEnd) return;

        ++frame;

        // オブジェクトを有効にする
        while(frame >= objList[nowObj].generateFrame)
        {
            if (objList[nowObj].waveObj)
            {
                objList[nowObj].waveObj.gameObject.SetActive(true);
            }

            NextObj();

            if (waveEnd) { break; }
        }
    }

    // 次のオブジェクトへ
    void NextObj()
    {
        if (nowObj < (objList.Count - 1))
        {
            ++nowObj;
            frame = 0;
        }
        else
        {
            waveEnd = true;
        }
    }

    // ウェーブ終了
    public bool IsEnd()
    {
        // オブジェクト毎の終了判定
        for (int i = 0; i < objList.Count; ++i)
        {
            if (objList[i].waveObj)
            {
                if (!objList[i].waveObj.IsEnd())
                {
                    return false;
                }
            }
        }

        // 全てのオブジェクトが有効になっていれば終了
        return waveEnd;
    }

    // 全てのオブジェクトが消えたか
    public bool IsDelete()
    {
        for (int i = 0; i < objList.Count; ++i)
        {
            if( objList[i].waveObj )
            {
                if (objList[i].waveObj.gameObject)
                {
                    return false;
                }
            }
        }

        return true;
    }
}

 

ウェーブ管理クラス

Wave クラスを管理するクラス

Wave クラスが終了判定になったら次のウェーブを生成する

public class WaveManager : MonoBehaviour
{
    [SerializeField] List<Wave> waveList;       // ウェーブリスト
    [SerializeField, Min(0)] int waveIndex = 0; // ウェーブ番号

    List<Wave> cloneList = new List<Wave>();    // クローンリスト
    int cloneIndex = 0;                         // クローン番号
    bool listEnd = false;                       // 終了フラグ

    void Start()
    {
        StartWave(waveIndex);
    }

    void Update()
    {
        // ウェーブの削除確認
        for (int i = 0; i < cloneList.Count; ++i)
        {
            if (cloneList[i] && cloneList[i].IsDelete())
            {
                Destroy(cloneList[i].gameObject);
            }
        }

        if (waveList.Count <= 0 || IsEnd()) return;

        // ウェーブが終わった
        if(cloneList[cloneIndex].IsEnd())
        {
            // 次のウェーブへ
            NextWave();
        }
    }

    // ウェーブ開始
    void StartWave(int _index)
    {
        cloneList.Add( (Wave)Instantiate(waveList[_index]) );
    }

    // 次のウェーブへ
    void NextWave()
    {
        if(waveIndex < (waveList.Count - 1))
        {
            ++waveIndex;
            ++cloneIndex;
            StartWave(waveIndex);
        }
        else
        {
            listEnd = true;
        }
    }

    // 全てのウェーブが終了したか
    public bool IsEnd()
    {
        return listEnd;
    }
}

waveIndex

インスペクタービューで設定できるようにして

確認したいウェーブから始められるようにする

 

エディタ画面

空のオブジェクトを作成して、Wave をアタッチする

作成したオブジェクトを親にして、WaveObj を継承したオブジェクトを追加

最後にプレハブ化する

ウェーブのオブジェクトリスト
最後のwaveobjなしは待機フレーム
ウェーブのプレハブ
3つのウェーブを用意

 

空のオブジェクトを作成して、WaveManager をアタッチ

プレハブ化したウェーブを設定する

ウェーブ管理クラスのウェーブリスト
確認したいWaveがあれば、Indexの数値を変更する

 

サンプル動画

試しに3つのウェーブを作ったものです

ウェーブ2は全ての敵を倒さないと次に進まない仕様

 

さいごに

ステージ作るためのシステムができたので

ステージを構成するオブジェクトを増やしていきたい!

 

かれいど

ゲームをしたり、作ったり
色々な事に挑戦していきたい!

サッカー観戦も趣味で
主にJ1リーグを観ています。

かれいどをフォローする
unity
スポンサーリンク
シェアする
かれいどブログ

コメント