【Unity】RPGを作るチュートリアルその62 エンカウントの動作を管理するクラスを作成

【Unity】RPGを作るチュートリアルその62 エンカウントの動作を管理するクラスを作成

シンプルなRPGをUnityで作るチュートリアルシリーズの62回目です。

第61回ではエンカウントの機能を実装していくにあたって、エンカウントに関する定義データを作成しました。エンカウントはマップの動作とも関連するので、そちらと並行して作成していきます。

今回はエンカウントの動作を管理するクラスを作成していきます。

 

 

制作環境

MacBook Pro 2023 Apple M2 Max

Unity6 (6000.0.30f1) Silicon

 

作業内容と順序

シンプルなRPGを作る上でどんな作業が必要か、どんな順番で作っていくと良さそうか、別ページで検討しました。基本的にこの流れに沿って進めていきます。

 

チュートリアルの一覧

このシリーズ全体の一覧は以下のページにまとめています。

 

前回の内容

前回はエンカウントの機能を実装していくにあたって、エンカウントに関する定義データを作成しました。

 

エンカウントの動作について

前回はエンカウントの定義データを作成しました。今回はその定義データをもとに、エンカウントを発生させるクラスを作成していきます。このクラスでは、現在のマップに対応するエンカウント定義データを使って、キャラクターの移動後にエンカウントが発生するかどうかを抽選します。エンカウントが発生する場合は、どの敵キャラクターが出現するのかも抽選していきます。

敵キャラクターの抽選後は「BattleManager」に敵キャラクターのIDを通知して、戦闘を開始します。エンカウントによる戦闘が始まった場合、戦闘終了後にこのクラスに通知を行なって、移動できるように処理を行いたいと思います。通知に関してはインタフェースを用意していきます。このインタフェースは、エンカウントの管理クラスで使う他に、イベントによる戦闘を開始するクラスでも使いたいと思います。

主人公キャラクターの移動後にエンカウントの管理クラスの処理を呼びたいため、キャラクターの移動クラスについても改修を行います。

作業の順序としては、

  • インタフェースの作成
  • エンカウントの動作を管理するクラスの作成
  • 「BattleManager」の改修
  • 「CharacterMover」の改修
  • 「PlayerMover」の改修

になります。

 

戦闘完了の通知を受け取るインタフェースの作成

「BattleManager」から通知を受け取るインタフェースを作成します。戦闘関連のファイルなので、Projectウィンドウから「Assets/Scripts/Battle」のフォルダに移動し、空のスクリプトファイルを作成します。名前は [IPostBattle] にしました。

インタフェースの作成
インタフェースの作成

 

作成した「IPostBattle」の中身は以下のように記載しました。

 

OnFinishedBattle()は戦闘に勝った場合、またはこちらが逃げた場合のコールバックです。もう一方のOnLostBattle()は戦闘に負けた時のコールバックです。エンカウントの場合、イベントの場合と、それぞれ個別に処理を行う想定なので、呼び出し元に処理を戻すようにしています。

 

エンカウントの動作を管理するクラスの作成

続いてエンカウントの動作を管理するクラスを作成していきます。このクラスで実装したい機能としては、

  • 「BattleManager」への参照を保持するフィールド
  • 「CharacterMoverManager」への参照を保持するフィールド
  • 現在のマップのエンカウントデータを保持するフィールド
  • 現在のマップのエンカウント情報をセットするメソッド
  • 移動後にエンカウントが発生するかどうか確認するメソッド
  • エンカウントの抽選メソッド
  • エンカウントする敵キャラクターのIDを抽選するメソッド
  • 戦闘終了時のコールバックメソッド
  • 戦闘で負けた時のコールバックメソッド

です。下の2つはインタフェースによって実装が強制されるものです。

Projectウィンドウから「Assets/Scripts」のフォルダに移動し、新しくフォルダを作成します。名前は [Map] にしました。ここにマップ関連のファイルを配置していきます。

フォルダの作成
フォルダの作成

 

作成した「Map」フォルダに移動し、MonoBehaviourのスクリプトファイルを作成します。名前は [EncounterManager] にしました。

スクリプトファイルの作成
スクリプトファイルの作成

 

作成した「EncounterManager」の中身は以下のように記載しました。

「BattleManager」への参照は戦闘の開始処理に使用し、「CharacterMoverManager」への参照はキャラクターの移動を停止/再開させるために使用します。今の状態ではキャラクターの移動の制御は「BattleManage」の中で行なっていますが、イベントによる戦闘後に移動できるようになってしまうのを防ぐため、エンカウントの管理クラスで制御するようにしたいと思います。

SetCurrentEncounterData()はマップが表示されるときに呼ばれる想定で、現在のマップに対応するエンカウントの定義データがセットされます。

CheckEncounter()は外部から呼び出すメソッドで、エンカウントが発生するかどうかを確認します。発生しない場合はキャラクターの移動などを止めずに処理を抜けます。このメソッド内でエンカウントの発生を確認しているのがIsHappenEncounter()のメソッドです。定義データを確認して、エンカウントのあるマップか、エンカウントがあればその確率から発生するかどうか、敵キャラクターの出現のしやすさは0より大きいか、といった点を確認してエンカウントが発生するかを判断します。

エンカウントが発生する場合、GetEncounterEnemyId()のメソッド内でリストのどの敵キャラクターが出現するのか判断します。出現のしやすさの合計値を計算し、その範囲の乱数を取得、出現のしやすさを順次乱数から引いていって、0未満になったらその敵キャラクターが抽選されたと判断します。UnityのRandom.Range()では、引数がintの場合は右側で指定した値は含まれないので、最後まで残っても0未満にならないことはないはず……!

OnFinishedBattle()は戦闘勝利または逃走で終了する場合のコールバックで、エンカウントによる戦闘ではキャラクターの動作を再開するようにします。

OnLostBattle()は戦闘に負けた時の処理で、村長のいるマップに戻す想定ですが、今はまだ実装していないのでコメントだけ残しています。

 

「BattleManager」の改修

「BattleManager」ではキャラクターの移動を停止したり再開していた部分を削除し、戦闘後のコールバック用インタフェースを保持するようにします。戦闘終了時は、インタフェースの対応するメソッドを呼び出すようにしましょう。

フィールドの追加部分では、「IPostBattle」への参照を保持するようにします。「CharacterMoverManager」への参照用フィールドは削除しました。

 

続いてコールバックの登録用メソッドを追加します。既存のSetUpEnemyStatus()とStartBattle()の間に追加しました。また、StartBattle()内の「CharacterMoverManager」のメソッド呼び出しは削除しました。

 

戦闘終了時の処理に関しては、キャラクターの移動を再開する処理を削除し、インタフェースの対応するメソッドを呼ぶように変更しました。

 

「CharacterMover」の改修

次に「CharacterMover」の処理を一部改修します。キャラクターの移動コルーチンが完了した後、後続の処理を呼び出せるようにします。NPCには影響はありませんが、主人公キャラクターに関しては、エンカウントの確認処理を呼び出したいため、virtualなメソッドを追加したいと思います。

既存のMovePlayerProcess()のコルーチンの最後に、今回追加するPostMove()の呼び出しを追加します。PostMove()は継承先のクラスで処理を書けるように、virtualにします。

 

「PlayerMover」の改修

「PlayerMover」のクラスも改修していきます。「EncounterManager」への参照を取得して、エンカウントの確認処理を呼び出します。

GetReference()で「EncounterManager」への参照を取得します。また、PostMove()をoverrideしてエンカウントの確認処理を呼び出しています。

 

スクリプトのアタッチ

スクリプトを保存したら、ゲームオブジェクトの作成してスクリプトをアタッチしましょう。

 

EncounterManagerのアタッチ

Hierarchyウィンドウからシーン直下にある「Managers」のゲームオブジェクトを選択し、子オブジェクトとして空のゲームオブジェクトを作成しましょう。名前は [EncounterManager] にしました。

ゲームオブジェクトの作成
ゲームオブジェクトの作成

 

Inspectorウィンドウで今回作成した「EncounterManager」をアタッチします。必要な参照についてもアサインしましょう。

スクリプトのアタッチと参照のアサイン
スクリプトのアタッチと参照のアサイン

 

動作確認についてはマップの管理機能を実装した際に行います。

 

今回のブランチ

 

まとめ

今回はエンカウントの動作を管理するクラスを作成しました。付随して、戦闘機能の側も少し修正を加えています。

次回はマップの管理の仕組みを考えつつ、マップを制御するクラスから作成していきます。

     

ゲーム開発の攻略チャートを作りました!

CTA-IMAGE

「ゲームを作ってみたいけど、何から手を付けていいか分からない!」


そんなお悩みをお持ちの方向けに、todoがアプリをリリースした経験を中心に、ゲーム作りの手順や考慮すべき点をまとめたe-bookを作成しました。ゲーム作りはそれ自体がゲームのように楽しいプロセスなので、「攻略チャート」と名付けています。


ゲームを作り始めた時にぶつかる壁である「何をしたら良いのか分からない」という悩みを吹き飛ばしましょう!