🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

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

Unity

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

Q&A

解決済

1回答

8508閲覧

【Unity2D】プレイヤーを追いかける敵を作りたい!【NavMeshAjent】

Uch_

総合スコア2

C#

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

Unity

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

0グッド

0クリップ

投稿2021/01/04 07:18

編集2021/01/09 12:55

1/7 : 追記しました。
1/9 : 自己解決しました。
###初めに
Unity2Dで、プレイヤーを追いかける敵キャラを作りたいと考え、NavMeshAgentを使ってみました。
しかし、参考にするサイトがいずれも3Dの場合で、私の環境とは異なるので、なかなかうまくいかなかったのですが、こちらの2019-2Dのコードを見つけました。(以下、☆とする)
以下、私が実行したことを列挙します。
また、今回は**「宇宙飛行士(Player)にインベーダー(AlienSpaceship)が追いかけてくる」**という状況をつくろうとしています。

1.タイルマップを設置
:今回はテストですので、障害物はないマップを作りました

2.GridごとTilemapを静的に変更

3.GridのTilemapにTilemapCollider2Dと、☆からDLしたNavMeshSourceTag2Dを付与

4.空のGameObjctを作成し、それに☆からDLしたNavMeshBuider2Dを付与。

5.値をなにもいじらずにそこのBakeをクリック。
:なぜかコンソールにエラーが残っているとうまくBakeできなかったので、コンソールをリセットしました。

6.ナビゲーションウインドウを開くと、マップ全体が青がかっていました。
:これでメッシュは正常に生成されていると思います。

イメージ説明

7.インベーダー(AlienSpaceship)に次のスクリプトを付与

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.AI; 5 6public class Alien_move: MonoBehaviour 7{ 8  //追いかける目標、今回はPlayer。 9 public GameObject target; 10 11  //毎フレームルートを考えることで、無駄なく動かせるようにする 12 void Update() 13 { 14      //agentを作成 15 NavMeshAgent agent = GetComponent<NavMeshAgent>(); 16      //目標をtargetに設定 17 agent.destination = target.transform.position; 18 19 } 20}

8.インベーダーのインスペクター画面で、targetにPlayerをアタッチし、NavMeshAgentを付与

9.ゲームを起動

イメージ説明

10.警告とエラーが多数が吐かれ、インベーダーが動かないので手動で停止
警告は

Failed to create agent because there is no valid NavMesh

エラーは

"SetDestination" can only be called on an active agent that has been placed on a NavMesh.

UnityEngine.AI.NavMeshAgent:set_destination(Vector3)
Alien_move:Update() (at Assets/Scenes/Scripts/Enemy/Alien_move.cs:17)

###問題点:
警告の内容から、そもそもNavMeshが生成されていないようです。しかし、6の作業でNavMeshが生成されていることが確認できているので、矛盾しています。
メッシュはできていることが確認出来ていて、かつインベーダーにも動けるようなコードを与えていることから、インベーダーの方ができているメッシュを認識できていないと考えます。
また、調べてもどの記事も3Dで解説されている上に、☆のスクリプトを用いている記事が少ない。

###解決するためにやるべきだと考えていること:
もしかしたら、何かレイヤーの違いのようなもので、情報共有ができていないのではないかと考えます。ですので、そのねじれを解くことが問題解決のカギになると考えています。

==========

###試した解決策:
・TilemapCllider2Dの「トリガーにする」と「エフェクターで使用」にチェック
・NavMeshSourceTag2DのAreaの値を変更
・インベイダーのUpdate内の作業を、開始から10秒後に動作するように変更
:警告はすぐ出たが、10秒後にエラーを吐き始めた
・エージェントタイプをデフォルトであった、Humanoidから、自作の適当なエージェントに変更。
・デフォルトであった、Humanoidの値を大きくしたり、小さくしたりした

いずれも、同じように警告とエラーを吐いて終わりました。

###補足:
ナビゲーションウインドウのBakeを押しても反応しませんでした。

###質問内容:
まずは、私のエラーへの見解があっているかどうか。つぎに、やるべきことがあっているかどうか。
最後に、どうやってやるべきことを実行するか。
ついでに、もし普通のNavMeshを2D環境で使う方法があるならそれを教えていただけると嬉しいです。

長文失礼いたしました。
よろしくお願いしたします。

###追記
返答をいただいた方から、ご指摘を頂きました。
作業4で作ったGameObjectのNavMeshBuilder2DのBakeOnEnableにチェックを入れていませんでした。
また、マップが正常に生成されているかどうかを見るためによりデコボコしたマップでメッシュを生成したときの画像を添付します。
イメージ説明

また、この変更により新しい警告が出てきたので、追記させていただきます。

Failed to create agent because it is not close enough to the NavMesh

UnityEngine.AI.NavMesh:AddNavMeshData(NavMeshData)
NavMeshBuilder2D:RebuildNavmesh(Boolean) (at Assets/NavMeshComponents-2019.3-2D/Assets/NavMeshComponents/Scripts/NavMeshBuilder2D.cs:88)
NavMeshBuilder2D:OnEnable() (at Assets/NavMeshComponents-2019.3-2D/Assets/NavMeshComponents/Scripts/NavMeshBuilder2D.cs:34)

やはり推察通り、agentがNavmeshを正常に確認できていないようです。
このエラーを調べたところ、次の解決策でうまくいったという方がいたので、試してみました。
1.ベースオフセットの値を変える
2.NavMeshBuilder2Dの更新方法を手動から更新にする
3.NavMeshSurfaceを追加し、そこでBakeする
これをした後に実行してみると、以下のエラーが増えました。

ArgumentException: The Object you want to instantiate is null.

UnityEngine.Object.CheckNullArgument (System.Object arg, System.String message) (at <480508088aee40cab70818ff164a29d5>:0)
UnityEngine.Object.Instantiate[T] (T original) (at <480508088aee40cab70818ff164a29d5>:0)
Alien_move.Start () (at Assets/Scenes/Scripts/Enemy/Alien_move.cs:15)

また、TilemapにNavMeshSurfaceを追加し、そこでBakeすると治った方がいるようなので試してみましたが、結果は変わりませんでした。
というのも、その方はAgentTypeが既定?のHumanoid以外で実行されており、この方法はそれを解消する方法らしいです。私はそのままHumanoidを使っているので、効果はないみたいです。

また、以下のコードを追記することで治った方がいるようです。

C#

1GameObject _prefab = (GameObject)Resources.Load ("Characters/" + _type); 2GameObject _character = Instantiate (_prefab); 3_character.GetComponent<NavMeshAgent> ().enabled = true; 4

これを私のAlien_move(作業7で追加したコード)のStart()に入れたところ、_typeが未定義ということで弾かれてしまいました。

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

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

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

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

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

sakura_hana

2021/01/05 03:03

「なぜかコンソールにエラーが残っているとうまくBakeできなかったので、コンソールをリセットしました。」の部分ですが、これはエラー表示を消しただけでエラーが解決したわけではありません。 なので残ったエラーが原因でBakeできていない可能性があります。(手順6で出来ているように見えても「ナビメッシュは生成されているが、そのメッシュが正常ではない」かもしれません) Bake前のエラー内容を確認してください。
Uch_

2021/01/05 07:21

回答ありがとうございます。 説明不足で申し訳ありません。 「なぜかコンソールにエラーが残っているとうまくBakeできなかったので、コンソールをリセットしました。」の部分でのエラーというのは、本文の手順10で出た、 "SetDestination" can only be called on an active agent that has been placed on a NavMesh. UnityEngine.AI.NavMeshAgent:set_destination(Vector3) Alien_move:Update() (at Assets/Scenes/Scripts/Enemy/Alien_move.cs:17) のエラーです。前回実行してみたときのものが残っていたのです。 確かに、ナビメッシュは生成されてはいるけど、そのメッシュが異常という可能性はあると思います。 しかし、bake前、bake後、実行前のコンソールにはいずれも一切警告エラーは出ていないので、わかりかねるんです。 また自分で調べたところ、3Dの環境ではAgentで動かすオブジェクトがメッシュの上にいないと動かないようです。私の環境は2Dですので、そもそも上と下みたいな関係はないはずなのですが、もしかしたらと思い立ったので書かせていただきます。それは関係ないでしょうか?
sakura_hana

2021/01/06 00:48

エラーについては了解です。 実際に試していないので間違っていたらすみませんが、以下のページにある「実際に使う場合はBakeOnEnableにチェックを入れる必要があります。」の部分は設定できていますか? https://watablog.tech/2020/09/29/post-1886/ あとマップの形を変えたり穴を空けたりしてBakeが正しく出来ていそうか確認出来るようにしてみてください。 またプレイヤーの位置(座標)が本当にマップ上かを確認してください。(知らない内にZ軸がとても離れている等の可能性があります)
Uch_

2021/01/07 02:47

返答ありがとうございます。 BakeOnEnableはチェックしていませんでした。ありがとうございます。 穴をあけたり、削れたマップを作製し、Bakeしたところ、正常にデコボコなメッシュができました。なので、メッシュは正常に作成できているようです。追記部分に画像を上げてあります。 テストで実行している間、Tilemap、Grid、Player、AlienSpaseshipのZ軸を監視しましたが、いずれも0で変化しませんでした。 新たな警告が出たので、追記部分を確認してください。 よろしくお願いします。
guest

回答1

0

自己解決

##自己解決
回答してくれた方には申し訳ないのですが、そもそもやり方が違いました。
これから見てくれる方のために、うまくいったやり方を残しておきます。

1.アドオンをDL、解凍、設置

https://github.com/h8man/NavMeshPlus
↑のURLのGitLabのページから入手できるアドオンをDL、解凍、Assetの欄に置いてください。
本文の☆のデータが残っていると、データが競合して動かなくなるので、消去してください。

2.マップを設置

この工程が少々面倒です。
まず、地面、歩ける場所となる部分をTilemapを用いて作成します。
もし、障害物、壁などを追加したい場合は、二枚目のTilemapを用いてそれらを設置してください。(タイルマップごとで判定してNavMeshを作っているようなので、見た目は壁でも全部歩けるようになってしまします。)
ここでは、地面となるTilemapをGroud、壁のみを描いたTilemapをWallと呼びます。

3.NavMeshModifireを各Tilemapにアタッチ

作業1でインストールしたアドオンの中にNavMeshModifireというナニか(勉強不足でごめんなさい。)があるので、それを各Tilemapにアタッチします。コンポーネントの追加画面で検索をかければ出てきます。
ここで、いずれもOverrideAreaにチェックをいれます。すると、AreaTypeという欄が増えるので、歩け所が描かれているマップにはWalkable、歩けない場所、壁や障害物が設置されてるマップにはNotWalkableを設定します。今回はGroundをWalkable、WallをNotWalkableに設定します。

4.空のオブジェクトを作成

5.作業4で作ったオブジェクトにNavMeshSurface2dをアタッチ

NavMeshSurfaceとは別物なので注意です。NavMeshModifire同様、検索をかければすぐ出てきます。
まず要素の下の方にある、RotateSurfaceToXYをクリックします。すると、オブジェクトのTransform欄の回転の値が「-90.00001」になることを確認してください。
つぎにOverrideByGridと、CompressBoundsにチェックを入れてください。
最後にBakeを押すと、メッシュが生成されます。
ちゃんと、歩ける場所と壁が分かれてメッシュが生成されているか確認してください。
メッシュは青っぽいアミアミになってるのでわかりやすいと思います。
また、メッシュはNavMeshSurface2dがアタッチされているオブジェクトを選択しているときと、ナビゲーションウインドウを開いているときしか見えないので、注意してください。

6.動かすオブジェクト、追われるオブジェクトを作成し、タグをつける

マップの作製より先にやってもいいですが、今回は説明のために順番を付けています。
今回は追われるオブジェクトをPlayer、Playerを追うオブジェクトをAlienとします。
それらにタグを付けます。(付けなくても恐らく動きはしますが、今回私がうまくいった方法を説明しています。)
タグ自体は何でもいいですが、私はPlayerにPlayer、AlienにEnemyを付けました。

7.オブジェクトを動かすためのスクリプト作成

今回私のはAlien_moveにしました。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.AI; 5 6public class Alien_move : MonoBehaviour 7{ 8 9 [SerializeField] Transform target; 10 private NavMeshAgent agent; 11 12 void Start() 13 { 14 target = GameObject.FindGameObjectWithTag("Player").transform; 15 agent = GetComponent<NavMeshAgent>(); 16 agent.updateRotation = false; 17 agent.updateUpAxis = false; 18 } 19 20 void Update() 21 { 22 agent.SetDestination(target.position); 23 24 } 25}

Playerのところは、付けたタグに応じて変更してください。
書けたらこのスクリプトを保存、動かしたいオブジェクトにアタッチしてください。今回はAlienにアタッチします。
また、これのインスペクター画面のTargetに追いかけたいオブジェクトを入れます。
今回はPlayerをいれます。

8.動かしたいオブジェクトにNavMeshAgentをアタッチ

ここは何もいじる必要はありません。
でも、ここの値が動くための速度だったりするので、いじりたい人は勝手にどうぞ。

9.テスト

実際に再生して、動かしてみましょう。
ちゃんと動くことが確認できると思います。
今回は割愛しましたが、Playerを動けるようにすると、ちゃんと動いた先に動くようになります。

投稿2021/01/09 12:56

Uch_

総合スコア2

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問