Unityの視界の判定
前回までの記事で敵がランダムに目的地を決めて徘徊するようになった。前回までの記事↓
TPSのキャラ移動
ジャンプ
ダッシュ実装
自作キャラを動き回らせる
剣を振る方法
剣コンボ
足が浮く対策
剣の軌跡の作り方
燃える剣の必殺技
ステータス管理
ダメージ判定・処理
HPゲージ
敵の攻撃
メッシュ変形での範囲攻撃
ビーム攻撃
NavMeshの使い方
敵の徘徊
今回は敵に視界を設定し、Playerを見つけたら徘徊をやめて近づくようにしていく。また、障害物が邪魔な場合はPlayerが見つからないようにしていく。
Unityでの敵の徘徊の実装
視界システムの詳細と準備敵のステータス設定
スクリプト記述
目次にもどる
視界システムの詳細と準備
今回は敵のスケルトンを動かすスクリプトを2つ使用する。1つは以前の記事で制作したCharaNavi2(徘徊スクリプト)である。敵の徘徊
もう一つはEnemyidou1(敵がPlayerを追いかけるスクリプト)だ。
そしてShikai(視界スクリプト)を作りPlayerを見つけたら、スケルトンを動かすスクリプトをCharaNavi2→Enemyidou1に切り替えるといった仕様を目指す。
Playerと敵(スケルトン)の子要素としてゲームオブジェクトのCubeを配置する。
.jpg)
名前をEyeとして位置を3Dモデルの目のあたりに来るように適当に調整しよう。以下のように目の向きと3Dモデルの向きをきちんと合わせること。
スケルトンの向き
.jpg)
目の向き
.jpg)
Eyeのゲームオブジェクトは以下のようにコンポーネントのMesh Rendererにチェックを外して見えないようにしておこう。
.jpg)
またPlayerのゲームオブジェクトのタグをPlayerにしておこう。
.jpg)
目次にもどる
敵のステータス設定
敵のステータスとしてScriptableObjectを使って以下を追加する。視界距離
敵がPlayerを認識できる最大距離。名前はShikaikyoriとした。
視野角
敵がPlayerを認識できる角度。名前はShikaihabaとした。
視界スキャン間隔
視界距離&視野角でのPlayerチェックを行う頻度。名前はShikaikankakuとした。
移動間隔
Playerを確認し近づく際、移動する次の目標地点を決める間隔。名前はIdoukankakuとした。
徘徊に戻る距離
Playerを発見していてもこの距離離れると見失い徘徊行動に戻るようにする。名前はHaikaiModorukyoriとした。
なお、ScriptableObjectがわからない場合は以下の記事で紹介しているので確認してほしい。
ステータス管理
今回は以下のように設定してみた。

目次にもどる
スクリプト記述
以下のようにShikai(視界スクリプト)を記述し、スケルトン(敵ゲームオブジェクト)にアタッチする。シリアル化をしており、以下のようにゲームオブジェクトを指定する(charadataにはScriptableObjectを使った敵のassetファイルを指定)。
.jpg)
Updateメソッドの最初でコルーチンを使ってshikaikankakuの間隔で処理が行われるようにしている。
今回は敵を発見したらAnimatorcontrollerのパラメータであるPlayerkakuninをtrueにするようにしている。よって既にtrueの場合には視界処理を行う必要がないのでリターン。
続いてVector3 kyorikeisan = PlayereyePosition - EnemyeyePosition;としてPlayeと敵の目の位置の差を求め、float kyori = kyorikeisan.magnitude;としてベクトルの長さを出す。ベクトルの長さが敵のShikaikyori(視界距離)を超えているならPlayerを発見できないのでリターン。
次にvar angle = Vector3.Angle(enemyeye.transform.forward, kyorikeisan);のように記述している。
これでenemyeye.transform.forward(敵の目の前方向)のベクトルとkyorikeisan(敵の目からPlayerの目への方向)のベクトルの間の角度を求めている。

そしてif (angle > shikaihaba)としており、求めた角度がShikaihaba(視野角)を超えているならPlayerを見つけられないと判断してリターンする。今回はScriptableObjectでassetファイルのShikaihabaに60と記述したので、敵の目からの前方ベクトルの右60度・左60度の範囲がPlayerを発見できる視界となる。
if (Physics.Raycast(EnemyeyePosition, kyorikeisan, out rayzyouhou, shikaikyori))というように条件分岐。
EnemyeyePositionの位置からkyorikeisanの方向へshikaikyoriの長さのRayを放つ。何かに当たったらそのコライダー情報をrayzyouhouが受け取りif文の中身の処理が行われる。
続いてif (rayzyouhou.collider.gameObject.CompareTag("Player"))と条件分岐。PlayerタグがついたPlayerであれば中身の処理が行われる。中身の処理はanim.SetBool("Playerkakunin", true);で、ようやくPlayerの発見条件を満たしたのでPlayerkakuninをtrueにする。
ここでPlayerのタグがとれなかった場合、Rayを撃ったがPlayerに当たる前に他のゲームオブジェクトに当たったことを示す。敵とPlayerとの間に障害物があることがわかるのでリターンする。
視界を作り出しPlayerを判定することが可能となった。
続いてPlayerへ近づく処理だが、以下のようにスクリプトを記述しスケルトン(敵ゲームオブジェクト)にアタッチする。
このスクリプトについては以下の記事の徘徊スクリプトとあまり違いがない。
敵の徘徊
異なるのは次の目標位置がPlayerの周囲の位置となるようにしている点。これでPlayerに近づく移動を再現している。
また、最初にbool tekihaken = anim.GetBool("Playerkakunin");としてPlayerkakuninのパラメータを取得し、if (tekihaken == false)と条件分岐している。敵を見つけておらずパラメータがfalseならここでリターンして処理は終了となる。
if (kyori > charadata.HaikaiModorukyori)の条件分岐も追加している。HaikaiModorukyori(徘徊に戻る距離)よりも敵とPlayerとの距離が離れたら、パラメータのPlayerkakuninをfalseしてリターン。徘徊移動を再び行うようになる。
なお、徘徊行動スクリプトについても以下の記述を追加する。
CharaNavi2のUpdateメソッドのはじめ部分のみ。
Playerkakuninのパラメータを取得し、敵を既に発見しているならリターンして処理を行わないようにしている。
以上のように記述すれば徘徊中のスケルトンの後ろなどを通っても気づかれない。スケルトンの前方に出ると発見され追いかけられる。
続きの記事は以下。
敵AI