質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.53%
Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

910閲覧

一時的にNavMeshAgentの追跡および移動を強制的に止める方法(敵がリロード中は停止させたい)

UngerFlog

総合スコア2

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2023/05/12 21:49

編集2023/05/13 18:53

実現したいこと

  • 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")として
このステートに入った際は自分自身のポジションを参照させることで移動を止めようとしていた。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

UngerFlog

2023/05/13 09:50

すみません、そちらについて見落としていたため直します。
guest

回答1

0

自己解決

自己解決したためその内容を追記

改めてGunnerクラスのソースを見直し、if (deadover == false && NowReloading == false)の箇所とif (Reloadjudgetime == 200.0f)の箇所を調整することで意図していた処理を行うことに成功しました。

//if (deadover == false && NowReloading == false)の箇所に追加したものです else if (Detection == "ReloadingNow") { //リロード中もとりあえず止まっている想定 GetComponent<NavMeshAgent>().isStopped = true; } //中略します // リロード判定持続時間を超えたらFlaseにする if (Reloadjudgetime == 550.0f) { //リロード判定継続時間判定をFalse Reloadjudge = false; //リセットも忘れずに Reloadjudgetime = 0.0f; //ここでリチャージもリセット Attacktime = 0.0f; //リロードが終わったので動いていい GetComponent<NavMeshAgent>().isStopped = false; GetComponent<NavMeshAgent>().speed = 1f; NowReloading = false; Detection = "Chaseing"; }

投稿2023/05/13 09:53

UngerFlog

総合スコア2

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.53%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問