Unityで主人公キャラが近づいてきたら追いかける敵キャラを作る

今回は主人公キャラが敵キャラに近づいたら主人公に近づいてくるようにしたいと思います。

前回、敵キャラクターが見回りをするというスクリプトを組みました。

Unityのゲームで作った敵キャラクターが見回りをするように、ランダムに設定した位置に移動させる機能を作成します。

まずはスクリプトをどうやって組むか考えてみます。

敵キャラクターが『主人公キャラクターが近づいてきた』、というのがわからなければいけません。
これにはコライダ(接触判定に使う)を使います。敵が持つコライダと主人公キャラが接触していたら近づいているとします。

コライダの範囲が主人公キャラを検知できる範囲になりますね。

次に敵キャラが主人公キャラクターを追いかける。というのは敵キャラが移動する目的地を主人公キャラクターの位置に変更すればいいような気がします。

ただ目的地(主人公キャラ)は動くので常に監視し変更しなければいけません。
また敵キャラの検知範囲から主人公が外れた場合は敵キャラはまた見回りに戻る為、新しい目的地を設定するようにします。

スポンサーリンク

敵キャラが主人公キャラを検知する範囲を作成する

まずは敵キャラにコライダを設定します。

敵キャラのボーンの階層の下にSearch Areaという空のオブジェクトを作ります。(右クリック→Create Empty)

敵キャラのボーンの子要素にサーチエリアを作る

Add Component→Physics→Box Collider

を選択し主人公キャラの検知範囲を修正します。Is Triggerにチェックを入れてください。
(ここではBox Colliderを選択していますが、Sphere Colliderの方がいいです)。

BoxColliderのIsTriggerにチェックを入れる

Is Triggerにチェックを入れるとスクリプト上で接触の検知は出来ますが、物体としては当たらないようになります。

例えば木などにコライダを設定すると、その部分に侵入は出来ませんが、Is Triggerにチェックを入れると侵入可能となり、木をすり抜けていきます。

主人公キャラクターを検知する範囲

上のような検知範囲を設定してみました。

広く設定されているように見えますが、実際は足音が確実に聞こえる距離までいかないと相手は気づきません。

つまり今回の範囲であれば相当接近しなければ気付かれません。

次に検知範囲に入って来たものが主人公キャラクターであるという判別が必要です。
その為に主人公キャラクターにタグを設定します。

ゲームオブジェクトにタグを設定する

タグはそのオブジェクトがどういう種類に属するかを判別する為のもので、自分で作成する事も出来ます。

主人公キャラにPlayerという元々あるタグを設定してみます。なければAdd Tagで追加してください。

主人公キャラクターにPlayerタグを設定する

タグを追加したので、SearchAreaオブジェクトにSearchCharacterスクリプトを追加し「masasi」君を検知出来るようにします。

サーチエリア(コライダ)に主人公が進入したか調べるスクリプト

SearchCharacterスクリプトはその名の通り検知するスクリプトです。

OnTriggerStayメソッドはスクリプトが設定されているオブジェクトのコライダが他のコライダと接触中に実行されるメソッドです。

そこで接触したコライダが何だったかをタグを使って判定します。

上記のように記述し、引数colに接触した他のコライダが設定されるようになります。
接触した他のコライダのタグがPlayerの時に敵キャラが主人公を追いかけるようにすればいいという事になります。

接触したのがPlayerだった時で、敵キャラであるゾンビの状態が追いかける状態でなければ追いかける状態にします。

とします。MoveEnemyスクリプトのSetStateメソッドは後で作るのでここでは置いておいて、
第1引数にchaseという文字、第2引数にcol.transformで接触したオブジェクトのTransformを渡しています。

それではMoveEnemyスクリプト内にSetStateを作ります。

敵キャラが今どの状態にあるのか?という状態変数stateを宣言し、その状態を表すのに列挙型を使います。

特定の値だけ入れる事が出来る列挙型という変数

列挙型は普通の変数とは少し扱いが変わります。
宣言した項目以外の選択をしないようにする事が出来ます。

と宣言し、これを変数などに入れて使います。

C#だと整数型を指定する事が出来るみたいなんですが、JavaScriptだとどうやればいいかわかりませんでした・・。
型を割り当てない時はint型の数値が割り当てられwalkには0、waitには1と順番に数値が割り当てられます。

↑のようにすると

walk
wait
chase

という文字が表示されます。

State内の状態にそれぞれ値を設定する事も出来ます。

↑も同じように

walk
wait
chase

という文字が表示されます。

あらかじめ宣言された値以外をstateに入れるとエラーになるので、特定の値しか入れたくない場合は列挙型が活躍します。

敵キャラクターの状態変更メソッドの定義

敵キャラクターの状態変更をするSetStateメソッドを定義します。

第1引数で受け取った文字列で分岐させています。それぞれの分岐処理で状態の変化等をしています。

stateに入れている「EnemyState.名前」はenum State{}で宣言されていなければエラーになります。

フィールド宣言とStartメソッド内の追加と変更

フィールド宣言にEnemyStateフィールドとStartメソッド内でSetStateメソッドを呼び出し状態を初期化する処理を入れます。

敵の状態を表すEnemyState型のstateと追いかける状態になった時に追いかけるキャラクターのTransformを入れておくplayerTransformを宣言します。

状態によって処理を分岐させる

次にMoveEnemyスクリプトのUpdateメソッド内の処理を状態によって変更します。

目的地まで歩く処理とキャラクターを追いかける処理は目的地を指定すれば同じ処理を記述する事になるので、追いかける状態である時だけ目的地を再設定し、実際に移動させる処理は同じ処理をしています。

目的地に着いたら、待ち状態に変更します。

待ち状態である時は一定時間その場で待ち、指定時間を超えたら巡回状態(walk)に変更します。

主人公を検知するスクリプトSearchCharacterを改造

MoveEnemy内のスクリプトの記述が終わったので、SearchCharacterに戻ります。

現時点では敵がキャラクターを追いかける状態になったらそのまま一生追い続けます。(^_^;)

そこでSearchAreaに設定したコライダからキャラクターが出ていったら敵キャラクターを待ち状態に変更するようにします。

OnTriggerExitはオブジェクトが接触状態から抜けた時に呼ばれるメソッドなので、その時のオブジェクトのタグがPlayerであったら、敵キャラの状態を待機状態に変更しています。

これで追いかける処理と検知範囲外に出たら見失って一定時間待機し、再度見回りに戻るというスクリプトが出来ました。
簡単なAIではありますが、結構使えると思います。

もっと簡単に敵キャラの移動処理を作るなら

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

を使うと移動処理が簡単になります。
また、ナビゲーション機能を追加した後に

Unityのゲームで主人公キャラが壁等で見えない状態で敵の検知エリアに入っても敵は主人公を追いかけないようにします。

の機能を追加するとよりリアルな敵の動きが表現出来ます。

スクリプトがバラバラで解り辛かったので、修正を入れました。

オーバーロード機能は使う必要がなくなったので削除しました。(^_^;)

次回は敵キャラを最初から配置しておくのではなく自動で増やせるようにしたいと思います。

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます