Unityで主人公についてくるキャラクターを作成する

今回はUnityで主人公キャラを追いかけてくるサブキャラの作成をします。

サブキャラにはNavMeshAgentを取りつけてNavMeshしたフィールド上を歩ける状態にしておきます。
これに関しては前回の

敵キャラをUnityのナビゲーション機能を使って移動させる
Unityのナビゲーション機能を使って敵キャラクターを移動させます。ナビゲーション機能はあらかじめBakeされたフィールドを移動出来る機能です。

の記事でやりましたのでそちらを参考にしてください。

正直なところ前回の記事の内容の敵キャラが主人公を追いかけていくスクリプトと同じなんですが・・・・(^_^;)

今回はそれ専用のスクリプトを作って、記述しますので、他の機能とごっちゃになることはないかと思います。

スポンサーリンク

サブキャラクターの準備と追いかけるスクリプトChase

まずはサブキャラクターを用意し、アニメーターコントローラーをつけIdleとWalkの状態を作成してください。
アニメーターコントローラで使うパラメータはspeedというパラメータのみになります。

NavMeshAgentのコンポーネントを取りつけたら、さらに新しいスクリプトChaseを作成し取りつけます。
このChaseが主人公キャラを追いかける専用のスクリプトになります。

上のような変数を宣言します。

agentはNavMeshAgent、playerは主人公キャラクターをインスペクタで設定します。
arrivedは到着したかどうかの判定に使い、animatorはサブキャラのアニメーション制御で使います。

Start関数内でコンポーネントの取得と、エージェントの目的地をプレイヤーに設定します。

次に追いかける部分の処理を作成します。

到着していない場合は追いかける処理をさせますが、agent.remainingDistanceで目的地とサブキャラとの距離を調べ、目的地(主人公)と0.2mより下になったらagent.Stopでエージェントの動きを止めアニメーションをIdleにする為にアニメーションパラメータのspeedを0.0fに設定します。

到着フラグをOnにします。

目的地との距離がまだある場合はアニメーションパラメータをエージェントのスピード(インスペクタで設定できる)に設定します。

サブキャラが主人公キャラに到着していた場合は、主人公とサブキャラとの距離を計算し、10m以上になったらagent.Resumeでエージェントが再び動きだすようにします。

目的地は現在の主人公の位置に設定し、到着フラグをOffにします。
これでまた主人公と2m以内になるまで移動を始めます。

これで完成です!

・・・というだけでは前回のを少し変更しただけになってしまいますので・・・(^_^;)

サブキャラが主人公キャラの方を見る機能の追加

サブキャラが到着している間はサブキャラが主人公キャラを見るようにしてみます。

OnAnimatorIKは特別な関数で、アニメーターコントローラーのレイヤーの設定でIK Passのチェックを入れると、呼び出されます。

ではスクリプトを見ていきます。

まずはVector3.Dotでサブキャラが向いている方向と
プレイヤーの位置からサブキャラの位置を引いてプレイヤーキャラのいる方向
とのベクトルの内積を求めます。

ベクトルの内積とはなんぞや!?と思った方も多いと思いますが・・・わたしにもようわかりません。
簡単に言うと、サブキャラの向いている方向と主人公キャラのいる方向が完全に同じなら1、
反対方向なら-1が返ってきます。

という事は主人公キャラがサブキャラの見える範囲内180度以内の時にいれば正の値が
見えづらくなってきたあたりから負の値が返ってきます。

それを利用して、その値をweightに入れます。

animator.SetLookAtWeight(weight, 0, 1, 0, 0);
animator.SetLookAtPosition(player.transform.position + Vector3.up * 1.5);

animator.SetLookAtWeightでウエイトを指定します。
第1引数はウエイト、第2は体の関係度合い、第3は頭の関係度合い、第4は目の関係度合い、第5は間接が曲がる度合いの関係度合い、

自分なりに解釈してます・・・・。
パラメータを変更して試してみましたが、いまいちよくわかりません・・・。

とりあえずウエイトをさきほど指定したweightに設定します。
weightが負の値だった場合はウエイトを0にして主人公キャラを見ないようにします。

animator.SetLookAtPosition(player.transform.position + Vector3.up * 1.5);

で見るポイントを主人公に設定します。主人公キャラの基点は足元になっていますので、Vector3.upでY方向に1.5をかけ、
主人公の1.5mの高さの部分を見るようにしています。

第5の引数がキャラクターのモーションの制限なので、ここを0.5にすると変に体が曲がってしまう事がなくなります。
このパラメータを使えばさきほどのスクリプトのようにDot関数を使う必要もなくすっきり出来ます

第2引数の体のウエイトがありになると、体全体が主人公の方に向いてしまうので0にしました。

それではUnityの実行ボタンを押して試してみましょう。

チェイス5

静止画像だけで追いかけてくるかどうかわかりません・・・。
少年がガン付けられているようにしか見えませんね・・・。

とにかくサブキャラ(実はmasasi君)が主人公キャラを追いかけてきて、到着状態の時は主人公キャラを見るようになりました。

RPGのパーティの隊列を作る

主人公キャラクターが一定の距離離れたら追いかけてくるサブキャラの作成が出来たので、少しスクリプトを変更して、
RPGによくある主人公に付いてくる仲間たちを作りたいと思います。

仲間キャラクターをコピーする

仲間たちはさきほど使った「masasi」君をコピーして名前をmasasi2、masasi3とします。

主人公を含めたパーティー

↑のような感じで右から主人公、masasi、masasi2、masasi3となっています。
ちょっと怖い・・・・(^_^;)

masasi、masasi2、masasi3には新しくChaser2というスクリプトを作り取りつけます。
masasiに取りつけていたChaserスクリプトは取り外してください。

Chaserスクリプトでは主人公キャラクターが一定の距離離れたら追いかけるようにしていましたが、今回の場合は主人公キャラが動くたびに追いかけるようにします。
そして、主人公キャラクターと指定した距離の範囲内に入ったら止まるようにします。

public var charaDistance : float; // 付いていくキャラとの距離、この距離になったら止まる

publicでcharaDistanceを宣言し、主人公キャラクターと追いかける仲間との距離を指定出来るようにします。

Update関数内ではagent.remainingDistanceでエージェントの目的地との距離を取得し、それがcharaDistance以下になった時にエージェントを止めます。

エージェントを止めたらアニメーションも立っているものにしたいのでアニメーションパラメータのspeedに0を設定します。

それ以外の時は追いかけさせるのでagent.Resume()でエージェントの再開をします。
speedには1を入れ走るアニメーションが再生されるようにしています。

これだと追いかける時は常に走るアニメーションになるので、細かく設定したい場合は主人公キャラが歩いてるか走っているかの情報を取得して
歩いている時は追いかける時も歩きのアニメーション、走っている時は追いかける時も走っているアニメーションにするなどの設定をするといいかもしれません。

距離が近づいたら歩くアニメーションにするというのでもいいかも?

Update関数内では常にplayerに設定したキャラクターの位置を取得し、エージェントの目的地に設定しています。

ここであえて主人公と言わずキャラクターと言ったのは仲間全員が主人公を追いかける設定にしないからです。
そういう設定にすると主人公が怖いお兄さんに囲まれている怖い絵が出来上がるからです(T_T)/~~~

つまりは全員が主人公の近くによってしまいますので、本来やりたいRPGの隊列ようにはなりません。

そこでChaser2をmasasi、masasi2、masasi3に設定したらインスペクタのplayerにはそれぞれ

masasi→chara
masasi2→masasi
masasi3→masasi2

に設定し追いかけるキャラクターを別々にし、数珠繋ぎのような感じで指定してあげます。

masasi2のChaser2の設定値

masasi2のChaser2のインスペクタは↑のようになります。
前のキャラクターとの距離は1mに設定しました。

これでうまく追いかけてくれるかUnityの実行ボタンを押して確認してみましょう。

パーティの隊列機能が出来たかどうかの確認

↑のように主人公が移動すると仲間が前の人間を追いかけるようになりました。
怖いお兄ちゃんに追いかけられるどころか、軍人さんたちに追いかけられる少年に変わりました・・・・((+_+))