i-school - 2Dタイルマップ 発展5
 プレイヤーの後ろを追従するパーティメンバーを用意し、プレイヤーの進行方向に合わせて追従させる機能を実装します。
追従するメンバーについても、進行方向に応じたアニメの同期も行います。


<実装動画>
動画ファイルへのリンク



 以下の内容で順番に実装を進めていきます。

発展5 ープレイヤーの進行方向に合わせて追従するパーティメンバーの機能ー




 新しい学習内容は、以下の通りです。

 ・Tween.Kill メソッド



1.設計


 2Dゲームにおけるパーティメンバーの表現については、キャラクターが1名の時もあれば、
複数名のキャラがリーダーを追従している表現が用いられるケースがあります。

 今回は複数のパーティメンバーを用意し、リーダー役のキャラクターの移動に合わせて、
常に進行方向の後方に位置するように制御を行います。また、向いている方向のアニメの同期も行います。

 最初に提示している動画のような状態を目標に実装にチャレンジしましょう。



 このて順ではプレイヤーの移動処理は実装しません。事前に別途実装しておく必要があります。

 必要なオブジェクトとしては、パーティメンバー用のゲームオブジェクトを複数用意します。
あるいは、すでにあるゲームオブジェクトをそのまま利用します。

 この教材ではすでにあるリーダー役のゲームオブジェクトをそのまま利用してますが、変えておいた方がパーティメンバーとしての臨場感が増すでしょう。

 必要なスクリプトとしては、パーティメンバーの管理を行うためのマネージャー役のスクリプトを用意します。
それ以外はいままでのスクリプトを流用し、改良して対応します。

 ただし、説明上、必要になるスクリプトはすべて紹介します。
処理の内容を見直して、必要なもの以外は作成しなくても問題ありません。


2.プレイヤーのゲームオブジェクト(リーダー役)の子オブジェクトとして、パーティメンバー用のゲームオブジェクトを作成する


 任意の画像を使って、パーティメンバーとなるゲームオブジェクトを作成してください。
名前は任意ですが、PartyMember や PartyChara のように、わかりやすいものし、最後に通し番号を付けて、何人目であるかを明確に出来るようにしておいてください。

 後程、スクリプトをアタッチしてから複製しますので、今は1つだけ作成しておいてください。

 位置については、プレイヤーのゲームオブジェクトからみて、後方になるように配置してください。


ヒエラルキー画像



インスペクター画像



Sceneビュー画像



3.enum の PlayerDirection を作成する


 プレイヤーの向いている方向を示すための enum を作成します。
ここでは1つのファイルとして作成していますが、他のスクリプトに一緒に書いても問題ありません。

 すでに作成済の場合には、この手順は不要です。


PlayerDirection.cs

 <= クリックすると開きます。


 この情報を利用して、リーダー役のゲームオブジェクトの進行方向の情報をパーティメンバーにも参照させます。


4.PlayerAnimation スクリプトを作成する


 パーティメンバーのアニメの同期用のコントローラー・スクリプトを作成します。
ここでは MonoBehaviour を継承した状態で作成しています。

 すでに作成済の場合には、この手順は不要です。


PlayerAnimation.cs

 <= クリックすると開きます。




5.パーティメンバーのゲームオブジェクトに PlayerAnimation スクリプトをアタッチし、複製する


 先ほどリーダー役のゲームオブジェクトの子オブジェクトとして作成したパーティメンバーのゲームオブジェクトに
PlayerAnimation スクリプトをアタッチします。

 アタッチされていることをインスペクターで確認してから、複製して、メンバーを増やします。
何名でも構いませんが、合計2〜4名位にしておくとよいでしょう。

 この教材ではメンバーは2名で進めていきます。


ヒエラルキー画像



Sceneビュー画像



インスペクター画像



インスペクター画像




6.PartyMember スクリプトを作成する


 パーティメンバーを管理し、リーダー役のゲームオブジェクトから取得した進行方向の情報を利用して、各メンバーに命令を出すためのマネージャー用のスクリプトです。
このスクリプトはどのゲームオブジェクトにアタッチしても問題ありませんが、管理のしやすさから、今回はプレイヤー役のゲームオブジェクトにアタッチします。


PartyMember.cs

 <= クリックすると開きます。



7.<Tween.Kill メソッド>


 DOTweenの処理を強制的に終了するには、Kill メソッドを実行します。
この処理を実行することで、今回であれば Sequence によって組み立てられた移動処理を終了させることが出来ます。

 ただし、変数にDOTweenの処理を代入していない場合、動いている DOTween の処理を一時停止したり、再開したり、強制的に終了させる処理が実行できません

 この事態に対応するため、Tween 型の変数を宣言することで、DOTweenの処理内容を変数に代入することが出来ます。
また List で用意することで、複数の Tween 型をまとめて管理することが出来ます。

 Tween 型の変数に DOTween の処理を代入していることで、DOTweenの処理を一時停止させたり、再開したり、強制的に終了させることが出来るようになります。



 どのような場面で使用するかというと、無限ループの処理を終了させたり、処理を一時停止して、途中から再開したりできます。

 今回の場合は、移動の処理に DOTween を利用しています。
仮に移動処理中に次の移動の処理命令が来てしまった場合、DOLocalMove メソッドが重複してしまい、正常な移動処理ができなくなる恐れがあります。

 この状態を未然に防ぐためには、移動処理が残っている場合には前の処理を停止させて、新しい移動の命令のみを実行するように制御する必要があります。
そのためには、Tween 型の変数に移動の処理を代入しておく必要があるため、今回は Tween 型の List を用意して利用しています。


<この DOTween の処理を Tween 型の List に代入しておく>
// DOTween の処理を Sequence を利用して処理するため初期化 
Sequence sequence = DOTween.Sequence();
            
// 最初に先頭のキャラの位置に移動する。この処理を List に追加
tweenList.Add(sequence.Append(partyMemberAnims[index].transform.DOLocalMove(Vector3.zero, 0.25f)
    .SetEase(Ease.Linear)));
            
// その後で新しい位置に移動する。この処理を List に追加
tweenList.Add(sequence.Join(partyMemberAnims[index].transform.DOLocalMove(newPos * (index + 1), 0.25f)
    .SetEase(Ease.Linear))
    // 移動後、移動方向とアニメの同期をおこなう
    .OnComplete(() => 
    {
        partyMemberAnims[index].SyncMoveAnimation(-newPos);
        tweenList.Clear();
    }));


<そうすることで、実行中の DOTween の処理を停止できる>
// 前の移動処理が残っている場合
if (tweenList.Count > 0) {
  foreach (var tween in tweenList) {
      // 停止する
        tween.Kill();
    }
    tweenList.Clear();
}

 DOTween は大変便利な機能ですが、非同期処理であるため、一度動き出してしまった処理は実行中には制御できない、ということを覚えておきましょう。
それを制御するためには、実行命令のタイミングで Tween 型の変数に代入しておくことで対応出来ます。こちらも合わせて覚えておきましょう。


8.リーダー役のゲームオブジェクトに PartyMember スクリプトをアタッチする


 リーダー役のゲームオブジェクトに PartyMember スクリプトをアタッチします。

 アサイン情報などはありませんので、正常にアタッチされているかを確認しておきましょう。
 

インスペクター画像



9.PlayerManager スクリプトを作成する


 リーダー役のゲームオブジェクトの制御を行うためのマネージャー用のスクリプトを作成します。
今回は必要な機能のみ、抜粋して掲載します。そのため、リーダー役のゲームオブジェクトの移動処理の記述はありません

 このスクリプトも作成済の場合には、この手順はスキップしてください。


PlayerManager.cs

 <= クリックすると開きます。



10.リーダー役のゲームオブジェクトに PlayerManager スクリプトをアタッチする


 リーダー役のゲームオブジェクトに PlayerManager スクリプトをアタッチします。

 アサイン情報などはありませんので、正常にアタッチされているかを確認しておきましょう。
 

インスペクター画像



11.ゲームを実行して動作を確認する


 スクリプトが多く、外部クラスのメソッドの呼び出し命令もありますので、デバッグを行う際には、しっかりとソースコードの処理を読み解いていからゲームを実行してください。
自分でソースコードにコメントを書いてみて、上手く言語化ができない部分については、復習を行うようにしましょう。


<実装動画>
動画ファイルへのリンク



 以上で完成です。