実現したいこと
- NavMeshAgentを利用している敵を強制的に追跡および移動を停止させる
(敵のリロード中、プレイヤーが敵から離れてしまってもリロードを終えるまで敵に移動を一切させない方法)
前提
こんにちは、現在私はUnityの3Dでプレイヤーを追跡して
一定距離に近づいたら銃を撃ってくる敵を作成しており
リロードの際はプレイヤーが離れたとしても動かないようにしようとしています。
どのようにプレイヤーを検知しているかについて、敵の子オブジェクトとして
プレイヤーを追いかけるための当たり判定と銃を撃つ当たり判定を作成し
プレイヤーがその当たり判定に接触している場合
「追跡中」「見失った」などステートを遷移させる形にしており
リロードの際は強制的にNavMeshおよび移動を止めようとしたのですが
NavMeshの速度やisStoppedなどを調整しても止まることができませんでした。
NavMeshAgentによるプレイヤーの検知そのもの停止および
敵の移動を完全に停止させるにはどのようにすればよいでしょうか。
自分が考えていたものとしては、リロードの際という形でboolで管理を行い
切り替えられた際は、移動もNavMeshAgentの検知もできず
停止する形にしたいのですがどのようにすればよいでしょうか。
こちらは敵のソースです(不要な個所については省略しています。)
public class Gunner : MonoBehaviour { Transform player; NavMeshAgent nav; Animator animator; Transform WaitingPost; //死亡後存在時間判定用 float f = 0.0f; bool deadover = false; //プレイヤー検知用の子オブジェクトの変数 public string Detection = "Missing"; //攻撃アニメーションの判定 public string AttackInside = "WalkAnimate"; //ダメージ時間をカウントさせる private float Attacktime = 80.0f; //攻撃判定を一定時間Trueにさせる private bool Attackjudge = false; private float Attackjudgetime = 0.0f; //リロード判定も同じようにする private bool Reloadjudge = false; private float Reloadjudgetime = 0.0f; //死亡判定(効果音や攻撃に利用) bool ImDead = false; //待機場所用の格納(見失った際に移動する場所の判定を別に作成しています) [SerializeField] public GameObject WaitingPostBOX; //弾丸を格納している [SerializeField] GameObject Turret_Bullet_Prefab; private float ReloadCount = 0.0f; private bool NowReloading = false; void Start() { animator = GetComponent<Animator>(); player = GameObject.FindGameObjectWithTag("Player").transform; nav = GetComponent<UnityEngine.AI.NavMeshAgent>(); Detection = "Missing"; WaitingPost = WaitingPostBOX.transform; } void Update() { // transformを取得(自分自身を止めるために) Transform myTransform = this.transform; // 座標を取得 Vector3 pos = myTransform.position; // ローカル座標を基準に、回転を取得 Vector3 localAngle = myTransform.localEulerAngles; //通常時はプレイヤーの座標を取得、追跡を外れたら待機場所を設定 if (Detection == "Missing" || Detection == "Chaseing" || Detection == "AttackAnimate") { nav.SetDestination(player.position); } else if(Detection == "OverRap") { nav.SetDestination(WaitingPost.position); } else if (Detection == "ReloadingNow") { //ここのステートに入った際は自分自身のポジションを参照させることで止めようとしていました。 nav.SetDestination(myTransform.position); } else { nav.SetDestination(WaitingPost.position); } if (deadover == false && NowReloading == false) { //プレイヤーを見つけていない時は止まってること if (Detection == "Missing") { animator.SetTrigger("IDLE"); GetComponent<NavMeshAgent>().isStopped = true; } else if (Detection == "Chaseing") { //プレイヤーを追跡中の判定 animator.SetTrigger("Walk"); GetComponent<NavMeshAgent>().isStopped = false; } else if (Detection == "OverRap") { //プレイヤーを見失った際の判定 animator.SetTrigger("IDLE"); Detection = "OverRap"; } else if (Detection == "AttackAnimate") { //銃撃中は止まっている想定 GetComponent<NavMeshAgent>().isStopped = true; } else { animator.SetTrigger("IDLE"); Detection = "OverRap"; } } else { //死んだときに強制力を持つ GetComponent<NavMeshAgent>().isStopped = true; } //攻撃範囲にいるとどんどん攻撃リチャージがされていく while (AttackInside == "AttackAnimate") { //リチャージする Attacktime += 1.0f; break; } //リチャージを追えたら攻撃する if (Attacktime == 220.0f && ImDead == false) { //アニメーションをする animator.SetTrigger("Attack"); //リロードカウントを増やす ReloadCount += 1.0f; //七発撃ったらリロードのアニメーションを行う if(ReloadCount == 7.0f) { //リロード中は絶対動かないようにする GetComponent<NavMeshAgent>().isStopped = true; GetComponent<NavMeshAgent>().speed = 0f; //ステートも固定状態にする NowReloading = true; Detection = "ReloadingNow"; //リロードアニメーションをする animator.SetTrigger("Reload"); //リロードを完了させる ReloadCount = 0.0f; //リロード判定継続時間判定をTrue(リロード途中で撃ち始めないようにする) Reloadjudge = true; } else { //攻撃判定継続時間判定をTrue(連射を防ぐための機構) Attackjudge = true; } } //攻撃発生から一定時間だけ攻撃判定をTrueにさせておく //攻撃判定持続時間をカウント while (Attackjudge == true) { //リチャージする Attackjudgetime += 1.0f; break; } // 攻撃判定持続時間を超えたらFlaseにする if (Attackjudgetime == 15.0f) { //攻撃判定継続時間判定をFalse Attackjudge = false; //リセットも忘れずに Attackjudgetime = 0.0f; //ここでリチャージもリセット Attacktime = 0.0f; } //同様にリロード時間も計測するようにする while (Reloadjudge == true) { //リチャージする Reloadjudgetime += 1.0f; break; } // リロード判定持続時間を超えたらFlaseにする if (Reloadjudgetime == 200.0f) { //リロード判定継続時間判定をFalse Reloadjudge = false; //リセットも忘れずに Reloadjudgetime = 0.0f; //ここでリチャージもリセット Attacktime = 0.0f; //リロードが終わったので動いていいようにする GetComponent<NavMeshAgent>().isStopped = false; GetComponent<NavMeshAgent>().speed = 1f; NowReloading = false; Detection = "Chaseing"; } } //これは追跡の当たり判定の子オブジェクトから状態を取得するものです public void SetSwitchName(string str) { //このようにして強制的に切り替えようとしたのですが失敗しました。 if(NowReloading == false) { Detection = str; } } //これは攻撃の当たり判定の子オブジェクトから状態を取得するものです public void SetAttackAnimate(string str) { //このようにして強制的に切り替えようとしたのですが失敗しました。 if(NowReloading == false) { AttackInside = str; } } }
こちらは敵の追跡の当たり判定です(不要な個所については省略しています。)
public class Gunner_Chaseing_Script : MonoBehaviour { public string Found_it = "Chaseing"; public string OverRap = "OverRap"; //プレイヤーと接触(視界に入った)時を判定する void OnTriggerEnter(Collider other) { if (other.tag == "Player") { //下記から親オブジェクトのメソッド「SetSwitchName」に「Found_it」に格納された文字を代入するスクリプト gameObject.GetComponentInParent<Gunner>().SetSwitchName(Found_it); } } void OnTriggerExit(Collider other) { if (other.tag == "Player") { //下記から親オブジェクトのメソッド「SetSwitchName」に「OverRap」に格納された文字を代入するスクリプト gameObject.GetComponentInParent<Gunner>().SetSwitchName(OverRap); } } }
こちらは敵の攻撃の当たり判定です(不要な個所については省略しています。)
public class Gunner_Attack_Script : MonoBehaviour { public string Found_it = "AttackAnimate"; public string OverRapAnime = "Chaseing"; //プレイヤーと接触(視界に入った)時を判定する void OnTriggerEnter(Collider other) { if (other.tag == "Player") { //下記から親オブジェクトのメソッド「SetAttackAnimate」に「Found_it」に格納された文字を代入するスクリプト gameObject.GetComponentInParent<Gunner>().SetAttackAnimate(Found_it); //下記から親オブジェクトのメソッド「SetSwitchName」に「Found_it」に格納された文字を代入するスクリプト gameObject.GetComponentInParent<Gunner>().SetSwitchName(Found_it); } } void OnTriggerExit(Collider other) { if (other.tag == "Player") { //下記から親オブジェクトのメソッド「SetAttackAnimate」に「OverRap」に格納された文字を代入するスクリプト gameObject.GetComponentInParent<Gunner>().SetAttackAnimate(OverRapAnime); //下記から親オブジェクトのメソッド「SetSwitchName」に「OverRap」に格納された文字を代入するスクリプト gameObject.GetComponentInParent<Gunner>().SetSwitchName(OverRapAnime); } } }
試したこと
リロードの際、GetComponent<NavMeshAgent>().isStopped = true;や
GetComponent<NavMeshAgent>().speed = 0f;によって追跡や移動を止めようとした。
ステート管理の箇所で動かないように固定化させたようとした。
(例としてNowReloading = true;やDetection = "ReloadingNow";のように
SetSwitchNameでの上書きについても対応したうえで
ステート管理の箇所で動かないように固定化させたようとした。
また、else if (Detection == "ReloadingNow")として
このステートに入った際は自分自身のポジションを参照させることで移動を止めようとしていた。
回答1件
あなたの回答
tips
プレビュー