見出し画像

【Unity】3Dローグライクゲームの作り方〜Step11-6〜

前回の記事はこちら
前回はミニマップを改良しました。

敵の種類を追加

いつまでも敵が1種類だとつまらないので、種類を増やしてみたいと思います。有難いことに「RPG Monster Duo PBR Polyart」には2種類敵キャラクターが用意されているので、もう片方のカメっぽいキャラクターを追加してみましょう(勿論他のキャラクターを追加しても構いません)。
まずプレハブを用意します。Field上のEnemies階層下に追加したいキャラクターを配置し、名前を任意に変更します(筆者は「Enemy2」にしました)。

アニメーターコントローラーの設定

次にアニメーターコントローラーを新たに用意しましょう。
AnimatorControllersフォルダ内に新しくアニメーターコントローラーを追加し、名前を変更します(筆者は「EnemyAnimator2」にしました)。
EnemyAnimator1を開き、中身を全てコピーして下さい。それを新しく作成したアニメーターコントローラーの中に貼り付けましょう。

スクリーンショット 2020-10-15 2.52.09

上記のような流れになればOKです。もしEntryの線がWalkingに伸びていない時はWalkingを「右クリック」→「レイヤーデフォルトステートとして設定する」を選択するといいでしょう。
Triggerパラメーター「Attack」を追加しておくのも忘れずに行って下さい。
後は中身のアニメーションをそのキャラクターにあったものに入れ替えるだけです。
出来上がったら、先ほど作成した敵キャラクターのオブジェクトのControllerにこれを設定しておきます。

コンポーネントの設定

次に敵オブジェクトに必要なコンポーネントを追加したいと思います。
必要なコンポーネントは以下の通りです。

・Actor Params Controll → 項目設定しない
・Inventory
・Actor Movement
・Actor Attack
・Enemy Operation → 項目設定しない
・Actor Action
・Actor Use Items

数が多いですが(すみません)頑張って追加しましょう。また、それぞれの項目も忘れずに設定しておきます。ただし、上記で「項目設定しない」としたもの2つについては触らないようにお願いします。

EActorに追記

列挙定数EActorに以下を追記します。「TURTLE」は任意に変更して下さい。

TURTLE = 2

ここまでできたら、敵オブジェクトをプレハブ化し、ヒエラルキータブ内からは削除して下さい。

ExcelActorDataファイルに追記

まずはExcelActorDataファイルから行います。
まず1枚目に対応するID名などを入力します。

スクリーンショット 2020-10-15 3.44.25

次にstatusで指定した名前で新しいシートを作成し、そこに新たな敵キャラクターのステータスを入力しましょう。

スクリーンショット 2020-10-15 3.49.47

若干スライムより強くしてみました。
更にExcelActorDataクラスに以下のパラメーターを追記します。

public List<Params> Enemy2;

「Enemy2」は先ほどstatusで指定した値にしておきましょう。
これができたらXLSXファイルを保存(ダウンロード)し、Resources/Datasフォルダ内のものと置き換えます。

ExcelAppearDataファイルに追記

以下のようにします。id2からが追加した分です。

スクリーンショット 2020-10-15 4.11.45

ExcelAppearData.EnemyAppearDataクラスに以下のパラメーターを追記します。

public EActor id2;
public int lvmin2;
public int lvmax2;
public int rate2;

できたらXLSXファイルを保存(ダウンロード)し、Resources/Datasフォルダ内のものと置き換えましょう。
次にFieldクラスのSetEnemyメソッドを変更します。

private void SetEnemy(string name, int xgrid, int zgrid)
{
   EActor actorId = EActor.SLIME;
   ExcelAppearData.EnemyAppearData enemyAppear =
           appearDatabase.EnemyAppear.Find(n => n.floor == floorNum);
   if (name.Equals("Random"))
   {
       int maxRate = enemyAppear.rate1 + enemyAppear.rate2;
       int r = Random.Range(1, maxRate + 1);
       if (r <= enemyAppear.rate1) actorId = enemyAppear.id1;
       else actorId = enemyAppear.id2;
   }
   else if (!System.Enum.TryParse(name, out actorId)) return;
   ExcelActorData.ActorData actorData = actorDatabase.Data.Find(n => n.id == actorId);
   if (actorData == null) return;
   int lv = 1;
   if (actorId == enemyAppear.id1) lv = Random.Range(enemyAppear.lvmin1, enemyAppear.lvmax1 + 1);
   if (actorId == enemyAppear.id2) lv = Random.Range(enemyAppear.lvmin2, enemyAppear.lvmax2 + 1);
   GameObject enemyObj = (GameObject)Resources.Load("Prefabs/" + actorData.prefab);
   GameObject enemy = Instantiate(enemyObj, enemies.transform);
   enemy.GetComponent<ActorMovement>().SetPosition(xgrid, zgrid);
   enemy.GetComponent<ActorParamsController>().SetLv(lv);
   enemy.GetComponent<EnemyOperation>().target = playerMovement;
}

ビルドしたら、テストしたいと思います。​
その前にマップファイルの敵オブジェクトを「Random」か「Turtle(任意のID名)」にしておくと確認しやすいでしょう。

スクリーンショット 2020-10-15 5.34.57

ちゃんと新しい敵が追加されましたか?
サイズ調整も行っておきましょう。

次回はアイテムの追加方法をまとめたいと思います。

おまけ:敵が追いかけて来なくなる

という不具合を把握したので少し改善しました。

private bool DetectTarget(ActorMovement actorMovement)
{
   Field field = GetComponentInParent<Field>();
   Pos2D agrid = actorMovement.grid;
   Pos2D tgrid = target.newGrid;
   ObjectPosition room = field.GetInRoom(agrid.x, agrid.z);
   if (room == null)
   {
       if (agrid.x == tgrid.x)
       {
           for (int z = Mathf.Min(agrid.z, tgrid.z), ez = Mathf.Max(agrid.z, tgrid.z); z < ez; z++)
           {
               if (field.IsCollide(agrid.x, z)) return false;
           }
           return true;
       }
       if (agrid.z == tgrid.z)
       {
           for (int x = Mathf.Min(agrid.x, tgrid.x), ex = Mathf.Max(agrid.x, tgrid.x); x < ex; x++)
           {
               if (field.IsCollide(x, agrid.z)) return false;
           }
           return true;
       }
       return false;
   }
   if (field.IsInRoomOf(room, tgrid.x, tgrid.z)) return true;
   else
   {
       if (agrid.x == tgrid.x)
       {
           for (int z = Mathf.Min(agrid.z, tgrid.z), ez = Mathf.Max(agrid.z, tgrid.z); z < ez; z++)
           {
               if (field.IsCollide(agrid.x, z)) return false;
           }
           return true;
       }
       if (agrid.z == tgrid.z)
       {
           for (int x = Mathf.Min(agrid.x, tgrid.x), ex = Mathf.Max(agrid.x, tgrid.x); x < ex; x++)
           {
               if (field.IsCollide(x, agrid.z)) return false;
           }
           return true;
       }
   }
   return false;
}

敵が部屋にいる時もプレイヤーが同じ部屋にいない場合は、敵が通路にいる時と同じ判定をすることにしました。

この記事が気に入ったらサポートをしてみませんか?