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

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

新規登録して質問してみよう
ただいま回答率
85.51%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

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

Q&A

解決済

3回答

6644閲覧

巡回する敵AIについて

TKM_waiwai

総合スコア16

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

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

0グッド

1クリップ

投稿2017/01/03 17:47

編集2017/01/05 15:56

Unityにて3Dのゲームを作っています。
Playerから逃げる敵AIを作っており、ある程度近づくと逃げていきある程度距離が出来るとランダムにウロウロ巡回させるようにさせたいのですが、ランダムにウロウロしてくれずPlayerと離れている時はずっとその場で止まったままになってしまいます。
近づくと逃げてはくれますが。。。

現段階でさせようとしているのは敵に目的地を指定させており、その目的地に向かって進むようにし、その目的地に近づくと別の目的地がランダムで決められ今度はそこへ敵が向かうという流れを使ってランダムでウロウロ巡回させようとしています。
Playerとの距離が近くなるとMove関数が呼ばれ逃げます。
目的地との距離が近くなるとDoPatrol関数が呼ばれ次の目的地がランダムで呼ばれるというしくみになっています。
ですが、なぜか敵は止まったままになってしまいます。
恐らく目的地という物が存在出来ていないのかなと思うのですが、解決出来ませんでした。
どうしたらランダムで巡回してくれるでしょうか。
現状のEnemyソースに間違いや足りない箇所などがあればアドバイスよろしくお願い致します。

【巡回AIの参考URL】

http://tongullman.blogspot.jp/2015/11/unity-navmesh-ai.html

【編集】
ソースを一部書き直しました。
参考にしたURLを貼りました。

質問の仕方が下手で申し訳ありません。

C#

1using UnityEngine; 2using System.Collections; 3 4public class Enemy : MonoBehaviour 5{ 6 public float m_speed = 2.0f; //移動速度 7 public float m_rotation; //回転速度 8 public Transform m_target; //追いかけるオブジェクト 9 NavMeshAgent m_agent; 10 11 private static Vector3 m_position; 12 private float m_patroldistance; 13 private float m_targetdistance; 14 15 void Awake() 16 { 17 m_agent = GetComponent<NavMeshAgent>(); 18 } 19 20 void Start() 21 { 22 DoPatrol(); 23 } 24 25 void Update() 26 { 27 m_patroldistance = Vector3.Distance(this.m_agent.transform.position,m_position); 28 m_targetdistance = Vector3.Distance(this.m_agent.transform.position, m_target.transform.position); 29 30 //Playerとの距離が30f以下になると逃げる 31 if(m_targetdistance <= 30f) 32 { 33 Move(); 34 }else if(m_patroldistance < 15f) 35 { 36 DoPatrol(); 37 }else 38 { 39 m_agent.SetDestination(m_position); 40 } 41 } 42 43 void Move() 44 { 45 //ターゲットの方向を求める 46 Vector3 vec = transform.position - m_target.position; //m_target.position - transform.position; 47 //ターゲットの方に向く 48 transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(new Vector3(vec.x, 0, vec.z)), m_rotation); 49 //進む方へ移動 50 transform.Translate(Vector3.forward * m_speed); 51 } 52 53 public void DoPatrol() 54 { 55 var x = Random.Range(-50.0f, 50.0f); 56 var z = Random.Range(-50.0f, 50.0f); 57 m_position = new Vector3(x, 0, z); 58 m_agent.SetDestination(m_position); 59 } 60} 61

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

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

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

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

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

ozwk

2017/01/04 23:25

m_positionはなぜstaticにしているんですか?
guest

回答3

0

ベストアンサー

3Dゲームプログラミングは素人の回答ですみません、私はUnityもNavMeshAgentも触ったこともありません。

まず、この全体のソースの中で「NPCが進む」という行為はSetDestinationだけでできているでしょうか?
サンプルサイトの通りだと、SetDestinationしただけでNPCは移動しなければならないと思いますが、TKM_waiwaiさんのソースだとMoveではSetDestinationを呼んでおらず、Positionを適宜手動で更新しているように見えます。

void Move() { // この中でSetDestinationが呼ばれていないのはなぜですか? // (逃げる先(目的地)の算出方法が分からない?) // また、MonoBehaviorのtransformにアクセスしており // ここではm_agentの状態が一切更新されていない Vector3 vec = transform.position - m_target.position;m.position; transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(new Vector3(vec.x, 0, vec.z)), m_rotation); transform.Translate(Vector3.forward * m_speed); }

ここから、m_agent.SetDestinationのみで移動できるように設定されていないのではと疑いを持ちました。
(Velocityとかデフォルトで設定されているものなのかもしれませんが…)

適当なポジションをインスペクタから設定してSetDestinationをコールするものを作り、それだけで移動する状態かどうかまず確認してみてはどうでしょうか。

また、Update内で毎回SetDestinationする必要性もないはずです。
SetDestinationは目的値の設定で、目的値に移動する前に経路探索の計算が必要なはずで、再設定が無視される作りなのかもしれませんがサンプルサイトと比較すると無駄な呼び出しのように思われます。
Unityのサイトには複数回同じ目的地の設定を行うことについては書かれておらず、呼び出しから数フレーム後まで経路探索が有効とならない場合があるとだけ書いてあることから、この呼び出しは不健全に思えます。

void Update() { m_patroldistance = Vector3.Distance(this.m_agent.transform.position,m_position); m_targetdistance = Vector3.Distance(this.m_agent.transform.position, m_target.transform.position); if(m_targetdistance <= 30f) { // この中でSetDestinationが呼ばれていないのはなぜですか? Move(); }else if(m_patroldistance < 15f) { DoPatrol(); } /* サンプルサイト通りなら不要では? 距離が再び30f以上になると元のパトロール先に戻っていこうとする、ということですか? その場合、現在どのような移動を行っているかをフラグとして持ち 「逃げる」「パトロールする」というステートが切り替えられた時に SetDestinationを更新するようにした方が丁寧です else { m_agent.SetDestination(m_position); } */ }

投稿2017/01/06 02:02

編集2017/01/06 02:25
haru666

総合スコア1591

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

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

0

Update の中ですが、if の else がないせいじゃないでしょうか?

c#

1 //Playerとの距離が30f以下になると逃げる 2 if(プレーヤーとの距離 <= 30f) 3 { 4 プレーヤーから逃げる(); 5 }else if(目的地との距離 < 15f) 6 { 7 次の目的地を選ぶ(); 8 }else 9 { 10 目的地に移動(); // ← これがない 11 }

蛇足ですが、c# の場合、関数名とか日本語にすると読みやすいですよ。

投稿2017/01/03 23:40

編集2017/01/04 01:34
takeshi

総合スコア264

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

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

TKM_waiwai

2017/01/04 16:31

アドバイスありがとうございます! やってみます!
TKM_waiwai

2017/01/04 16:55

DoPatrol関数の中に入れている 「m_agent.SetDestination(m_position);」でその目的地へ移動しているはずなので、 else文に同じ文を追加したのですがやっぱりダメでした。。。
takeshi

2017/01/04 23:49

毎回 DoPatrol を呼んだら、毎回目的地がリセットされませんか?
TKM_waiwai

2017/01/05 16:01

毎回目的地がリセットされて良いはずなんです、、、
takeshi

2017/01/05 23:40

目的地に到着するごとに毎回でなく、毎フレームごとになってしまいますので、意図している動作と異なる気がします。
TKM_waiwai

2017/01/06 00:24

なるほど、確かにそうですね。 どの辺で毎回DoPatrolを呼んできてしまっていますか?
takeshi

2017/01/06 06:22

if( 自分に近かった ) 逃げる。 elseif( 目的に近かったら ) 次の目的地設定 else 現在の目的地に移動 となるべきかと思います。最後の else の際にも SetDestination にしてしまうと、目的地から遠くても次の目的地の設定になってしまうかと。
guest

0

2番めのelse ifって、実質到達不可になってますね。
最初のif文では30以下と記述していますが、15以下の状態は30以下の状態でもあるため、たとえ15以下であっても30以下のほうが実行されてしまっています。

なので、if文の記述を逆にしたら動きませんか?

投稿2017/01/04 07:36

edo_m18

総合スコア2283

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

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

ozwk

2017/01/04 07:54

よく見ると変数名違うんですよ
edo_m18

2017/01/04 07:57

お。ほんとだw コメントありがとうございます。
takeshi

2017/01/04 23:49

私も、その罠にはまりかけたんで、日本語記述をすすめてしまいました、、、
ozwk

2017/01/04 23:59 編集

patrolToAgentDistance targetToAgentDistance にすれば1文字目が違うからぱっと見でもわかりやすいですかね それでもTo以降が長い上に同じだから見間違えやすいんですが
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問