見出し画像

【Unity】シューティングを作る~敵生成編~

ご!ピクジンです。

今回もシューティングゲーム作りの続きです。
CSVファイルを元に敵を生成する仕組みを作りました。

概要

雑な図ですがこんなイメージ。

やることは単純。
・敵オブジェクトを生成するクラスEnemySpawnでCSVファイルを読み込む
・それを元に敵オブジェクトを生成する

ついでに敵オブジェクトがどういう動きするか決めるenemyNumもここで決めてしまいます。

画像3

CSVファイルは以下のものを使用します。
タテはいくらでも増やせますが、ヨコは11列です。

スクリーンショット 2021-01-22 22.58.48

行が生成する順番、列が生成位置のx座標です。

スクリーンショット 2021-01-22 23.02.22

どの敵を生成するかは整数値で決めています。
0以上の整数が前回作ったScriptableObjectのデータに対応しています。
生成しない場合は-1を入れておきます。

スクリプト解説

//敵を生成するクラス

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

public class EnemySpawn : MonoBehaviour
{
   [SerializeField]
   private List<string> fileName = new List<string>();
   int waveNum = 0;
   TextAsset csvFile;
   List<string[]> waveDate = new List<string[]>();
   [SerializeField]
   private int maxColumn = 11;

   [SerializeField]
   private EnemyManager enemyPrefab = null;

   void Start()
   {
       CSVload();
   }

   void CSVload()
   {
       csvFile = Resources.Load("Wave/" + fileName[waveNum]) as TextAsset;
       
       StringReader reader = new StringReader(csvFile.text);

       while (reader.Peek() != -1)
       {
           string line = reader.ReadLine();
           waveDate.Add(line.Split(','));
       }

       StartCoroutine(spawn());
   }

    IEnumerator spawn()
   {
       for (int line = 0; line < waveDate.Count; line++)
       {
           for (int column = 0; column < maxColumn; column++)
           {
               int num = int.Parse(waveDate[line][column]);
               if (num >= 0)
               {
                   float f = (column - (maxColumn - 1) / 2) * 0.5f;
                   Vector2 spanPos = new Vector2(f, transform.position.y);

                   EnemyManager enemy = Instantiate(enemyPrefab, spanPos, Quaternion.identity);
                   enemy.ParameterSet(num);
               }
           }

           yield return new WaitForSeconds(0.5f);
       }
       
   }
}

CSVファイルの読み込みについてはこちらを参考にしています。
というかまんまですね。ありがとうございます。

ファイルを読み込み、string型配列のリストに全部ぶち込んだらspawnコルーチンで1行ずつ生成していきます。
1行生成したら時間差で次の行、終わったらまた時間差で次の行って感じにするためのコルーチンです。

まず読み込んだものはstring型なので、int型に変換してあげます。
これで等式を用いることができます。

int num = int.Parse(waveDate[line][column]);

numが0以上なら生成するということなので、敵のプレハブを列番号に応じた位置へ生成し、EnemyManagerのenemyNumにnumを代入してやります。

//EnemySpawn

float f = (column - (maxColumn - 1) / 2) * 0.5f;
Vector2 spanPos = new Vector2(f, transform.position.y);

EnemyManager enemy = Instantiate(enemyPrefab, spanPos, Quaternion.identity);
enemy.ParameterSet(num);

これに伴い、EnemyManagerも少し変えました。

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

public class EnemyManager : MonoBehaviour
{
   EnemyHealth enemyHealth;
   EnemyMove enemyMove;

   [SerializeField]
   int enemyNum = 0;

   private void Awake()
   {
       enemyHealth = GetComponent<EnemyHealth>();
       enemyMove = GetComponent<EnemyMove>();
   }

   //変更点---------------------------------
   public void ParameterSet(int num)
   {
       enemyNum = num;

       EnemyParameters enemyParameter = Resources.Load<EnemyParametersList>("ParametersList").enemyParameters[enemyNum];

       enemyMove.pathSet(enemyParameter.movePath, enemyParameter.moveTime);
       enemyHealth.Enemy_HP = enemyParameter.hp;
   }
   //----------------------------------------
}

なんやかんやで動画のようになるわけです。
記事用なのでわかりやすく色付けときました。
0:黒、 1:赤、 2:黃

終わり

書いてて思いましたが、上から下ではなく下から上の順に生成するほうが直感的なように思います。

あと、どうせ自分しか弄らないプロジェクトなのでこのようなファイルを使いましたが、本来はもっとかしこい方法あるはずなので鵜呑みにしすぎないように。
こんなもんそのまま使ったらヒューマンエラーの元ですぜ。

またこんど。

いいなと思ったら応援しよう!