【Unity】RPGを作るチュートリアルその44 戦闘中にキャラクターの動きを止める

【Unity】RPGを作るチュートリアルその44 戦闘中にキャラクターの動きを止める

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

第43回ではUI単位のウィンドウ制御と、UI自体の制御を行うクラスのうち、コマンド入力の機能について作成しました。

今回はUIの作業を一度中断して、戦闘が開始したら操作キャラクターやNPCの移動を停止させる処理を入れていきたいと思います。

 

 

制作環境

MacBook Pro 2023 Apple M2 Max

Unity6 (6000.0.30f1) Silicon

 

作業内容と順序

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

 

チュートリアルの一覧

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

 

前回の内容

前回はUI単位のウィンドウ制御と、UI自体の制御を行うクラスのうち、コマンド入力の機能について作成しました。

 

戦闘中にキャラクターが動いていた!

前回の作業で動作確認を行なったところ、コマンド入力の上下キーに合わせて操作キャラクターまで一緒に動いてしまっていました。

Spriteが置き去りに
Spriteが置き去りに

 

戦闘中はキャラクターの動きを止めておきたいので、こちらの制御部分を作っていきましょう。

やりたいこととしては、

  • シーン内の「CharacterMover」に指示を出すクラスを作る
  • 移動を制御する「CharacterMover」で移動できるかどうかのフラグを作る
  • 「BattleManager」から指示を出すクラスに通知する

あたりです。

「BattleManager」から個別の「CharacterMover」に通知を行うのは大変なので、シーン内の「CharacterMover」をまとめて管理してくれるクラスを挟みたいと思います。

 

シーン内の「CharacterMover」に指示を出すクラス

このクラスの名前は「CharacterMoverManager」にしようと思います。そのままですね。

「CharacterMoverManager」では、シーン内の「CharacterMover」をリストとして保持して、そこに対して移動できるかどうかの指示を出していきます。「CharacterMover」側では自分自身の存在を「CharacterMoverManager」に登録するようにします。そのため、登録用メソッドを作っておきたいと思います。

Projectウィンドウから「Assets/Scripts」のフォルダに移動し、MonoBehaviourのスクリプトを作成します。名前は前述の通り [CharacterMoverManager] にしました。

スクリプトの作成
スクリプトの作成

 

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

「CharacterMover」をリストとして保持するフィールドとして「_characterMovers」を作って、RegisterCharacterMover()のメソッド内で追加していきます。「CharacterMover」からはRegisterCharacterMover()を呼び出して自分を追加するようにしましょう。

戦闘が始まるタイミングでStopCharacterMover()のメソッドを使って「CharacterMover」を停止させ、戦闘が終わるタイミングでResumeCharacterMover()のメソッドを使って「CharacterMover」を再開させていきます。

移動を止めるだけだとアニメーションがそのままになったりするので、アニメーションに関しても制御するようにしています。

これらのメソッド内で呼び出している「CharacterMover」のメソッドについてはこれから追加していくので、今はコンパイルエラーがあっても目を逸らして進めていきましょう。

 

「CharacterMover」で移動できるかどうかのフラグを作る

続いて「CharacterMover」を変更していきます。

移動できるかどうかのフラグを作って、移動処理の中からそのフラグを確認するようにします。また、自分自身を「CharacterMoverManager」に登録する処理もStart()の中から呼び出すようにします。

アニメーションの停止と再開、移動の停止と再開について、それぞれメソッドを用意して、「CharacterMoverManager」から呼び出すようにしましょう。呼び出す方はもう書いちゃったので、その名前に合わせて実装していきましょう。

変更箇所が多いので、一旦全文を表示した後、個別に説明を行なっていきます。

 

フラグの追加と自分自身の登録

まずはフラグの追加と自分自身の登録部分です。

フラグの「_isMovingPaused」を使って移動できる状態かどうかを判別します。

Start()のタイミングでRegisterComponent()を呼び出して、「CharacterMoverManager」に対して登録を行います。これから作成するNPCのコンポーネントで毎回「CharacterMoverManager」への参照をアサインするのは大変なので、FindAnyObjectByType<T>()のメソッドを使って参照を取得しています。

 

移動処理の変更

移動に関するMoveCharacter()のメソッドとMovePlayerProcess()のコルーチンの変更に関する部分です。

MoveCharacter()では、「_isMovingPaused」のフラグがtrueになっていたら処理を抜けるようにします。

また、MovePlayerProcess()のコルーチン内では、「_isMovingPaused」のフラグがtrueになっていたらその分の時間を完了予定時刻と、ポーズ中の時間に加算して移動処理を行わずに次のフレームに進みます。

フラグがfalseになった後、ポーズされていた時間の分だけ経過時間から差し引くことで、位置のずれが発生しないようにしています。

 

アニメーションと移動の停止、再開

アニメーションの停止と再開、移動の停止と再開を行うメソッドをそれぞれ追加しています。

アニメーションの停止や再開については、Animatorコンポーネントの「speed」の値を変更して実現しています。0にするとアニメーションが進まなくなります。

移動の切り替えは「_isMovingPaused」のフラグを使って表現しています。

 

派生クラスの修正

「CharacterMover」の中では移動が開始した後に処理を止めるようにしていますが、派生クラス側で移動の検知自体も止めておくと安心です。そのため、「PlayerMover」と「NpcMover」についても一部修正を加えていきます。

 

PlayerMoverの修正

「PlayerMover」ではキー入力を検知する前に「_isMovingPaused」のフラグを見て処理を抜けるようにします。

変更したのはCheckMoveInput()です。移動中かどうかの確認後、ポーズフラグを確認してtrueならその後に進まず抜けます。早めに抜けておくことで、キー入力によるキャラクターの向き変更を防いでいます。

 

NpcMoverの修正

「NpcMover」では移動処理の先頭で抜けるようにします。

MoveNpc()が呼ばれた後、移動のインターバルを確認する処理があるため、その前にポーズフラグの確認を入れています。

 

BattleManagerの修正

次に「BattleManager」も修正していきます。今回作成した「CharacterMoverManager」への参照を保持するフィールドを作成し、戦闘開始時にアニメーションと移動を停止するようにします。また、後で戦闘終了の処理を作る際にアニメーションと移動を再生する処理を入れるようにしましょう。

まずはフィールドの追加部分です。プロパティの前に入れました。

 

続いて戦闘開始処理での呼び出しです。戦闘開始処理の前に「CharacterMoverManager」のStopCharacterMover()のメソッドを呼ぶようにしています。

 

スクリプトのアタッチ

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

 

CharacterMoverManagerのアタッチ

「CharacterMoverManager」のスクリプトをアタッチするゲームオブジェクトから作成していきましょう。Hierarchyウィンドウでシーン直下の「Managers」の下に空のゲームオブジェクトを作成します。名前は [CharacterMoverManager] にしました。

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

 

Inspectorウィンドウでは「CharacterMoverManager」のスクリプトをアタッチします。

スクリプトのアタッチ
スクリプトのアタッチ

 

また、「BattleManager」のスクリプトでもフィールドを追加したので、「CharacterMoverManager」をアサインしておきます。

スクリプトのアサイン
スクリプトのアサイン

 

動作確認

ここまでの設定を終えたら動作確認をしてみます。ゲームを実行して、「BattleTester」のスクリプトにて「Execute Battle」にチェックを入れて戦闘を開始します。戦闘を開始した際、キャラクターのアニメーションと動作が停止していることを確認できればOKです。ゲームの実行中、「BattleParent」のゲームオブジェクトを非表示にすると確認しやすいかと思います。

ザ・ワールド!
ザ・ワールド!

 

今回のブランチ

 

まとめ

今回は戦闘が開始したら操作キャラクターやNPCの移動を停止させる処理を実装しました。

次回はUIの作業に戻って、魔法やアイテムの選択ウィンドウの制御、ウィンドウ内のUIの制御を行なっていきましょう。

 

     

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

CTA-IMAGE

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


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


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