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

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

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

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

スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

Unity

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

Q&A

解決済

2回答

1777閲覧

Unity2D環境でNPCキャラにNavを実装【NavMeshAgent2D版使用】

Kageyama_23457

総合スコア21

C#

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

スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

Unity

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

0グッド

0クリップ

投稿2020/02/04 11:27

編集2020/03/30 01:41

★3月30日 自己解決しました。自己解決欄に結論スクリプトを載せておきます。

###当該スクリプト
いきさつを書くと長くなるので、先に問題点だけ書きます。
以下のスクリプトAではエラーが出ないのに、BだとUnityでエラーが出ます。

スクリプトA(メインカメラにつける、プレイヤを追いかけるスクリプト)

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class camera : MonoBehaviour 6{ 7 GameObject _player; 8 void Start() 9 { 10 this._player = GameObject.Find("Player"); 11 } 12 void Update() 13 { 14 Vector3 _playerPos = this._forCamera.transform.position; 15 transform.position = new Vector3( 16 transform.position.x, _player.transform.position.y, transform.position.z); 17 } 18}

スクリプトB(Aを参考にして書いたもの。NavMeshAgent2D版を使うにあたり、エージェントオブジェクト←2D画像 と追尾させるために書きました。2D画像にアタッチ)

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class NPC_Surface : MonoBehaviour 6{ 7 GameObject Ri_Nav;//エージェントオブジェクト 8 9 void Start() 10 { 11 this.Ri_Nav = GameObject.Find("Risotto_Nav");//エージェントオブジェクト 12 } 13 void Update() 14 { 15 Vector3 Ri_Nav_pos = this.Ri_Nav.transform.position; 16 transform.position = new Vector3( 17 Ri_Nav_pos.transform.position.x, Ri_Nav_pos.transform.position.y, transform.position.z); 18 } 19}

エラー内容

CS1061: 'Vector3' does not contain a definition for 'transform' and no accessible extension method 'transform' accepting a first argument of type 'Vector3' could be found

同じゲーム内で、Aではエラーが出ないのに、Bではエラーが出ます。
他の方の目をお借りしたく質問致しました。タイポレベルのミスだったらごめんなさい。

以下、いきさつを書きます

作っているのは非営利目的のあるマンガの二次創作ゲームです。
2Dタテスクロールの障害物競争です。
NPCキャラに「障害物を避けつつゴールまで走る」という挙動を取らせたく、
こちら様を参考に実装しました。
NavMeshAgent2D版=タイルマップをもとに地形をベイクし、エージェントで走らせるというものです。
画像のように、地形のベイク及びエージェントの移動までは実装できました。
左の画像の左下のお茶がゴールで、右の画像の左下の緑の四角(見えづらいです)がエージェント本体です。
イメージ説明 イメージ説明
参考サイト様の最後にも書かれているのですが、
マップは2Dでもエージェント自体は3Dの扱いなので、
移動に伴い2D環境では必要のない回転などが加わってしまいます。
なので、
・キャラの画像(2DUI)にエージェントをつける
・キャラの画像をエージェントオブジェクトの子にする
という方法では、キャラの画像がクルクル回ってしまうという不具合が発生しました。

そこで上記の質問に至るのですが、
エージェントオブジェクト←キャラ画像(スクリプトでエージェントオブジェクトの座標を取得し同期)
という方法をとりたく、上記のスクリプトを書いたところエラーが出ました。
以下、関係ありそうなスクリプト3つを載せます。

エージェントオブジェクトのスクリプト

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.AI; 5 6public class NPC_Nav : MonoBehaviour 7{ 8 9 public NavMeshAgent Ri;//エージェントオブジェクト 10 public GameObject target;//ゴール 11 12 void Start() 13 { 14 Ri = gameObject.GetComponent<NavMeshAgent>(); 15 } 16 17 void Update() 18 { 19 if (target != null) 20 { 21 Ri.destination = target.transform.position; 22 } 23 } 24}

NavMeshAgent2D版の、タイルマップにアタッチするスクリプト(自作ではありません)

C#

1using UnityEngine; 2using UnityEngine.AI; 3using System.Collections.Generic; 4 5[DefaultExecutionOrder(-200)] 6[ExecuteAlways] 7public class NavMeshSourceTag2D : MonoBehaviour 8{ 9 public static List<NavMeshSourceTag2D> tags = new List<NavMeshSourceTag2D>(); 10 11 public int area; 12 Collider2D collider2D; 13 14 Mesh cachedMesh; 15 uint shapeHash; 16 17 void OnEnable() 18 { 19 collider2D = GetComponent<Collider2D>(); 20 tags.Add(this); 21 } 22 23 void OnDisable() 24 { 25 tags.Remove(this); 26 DestroyMesh(); 27 } 28 29 void UpdateCachedMesh() 30 { 31 if (collider2D == null) 32 { 33 DestroyMesh(); 34 return; 35 } 36 if (cachedMesh == null) 37 { 38 CreateMesh(); 39 return; 40 } 41 if (collider2D.GetShapeHash() != shapeHash) 42 { 43 DestroyMesh(); 44 CreateMesh(); 45 } 46 } 47 48 void CreateMesh() 49 { 50 cachedMesh = collider2D.CreateMesh(false, false); 51 shapeHash = collider2D.GetShapeHash(); 52 } 53 54 void DestroyMesh() 55 { 56 if (cachedMesh == null) 57 return; 58 59 if (Application.isPlaying) 60 { 61 Destroy(cachedMesh); 62 } 63 else 64 { 65 DestroyImmediate(cachedMesh); 66 } 67 shapeHash = 0; 68 } 69 70 // Collect all the navmesh build sources for enabled objects tagged by this component 71 public static void Collect(ref List<NavMeshBuildSource> sources, ref Bounds bounds) 72 { 73 sources.Clear(); 74 for (var i = 0; i < tags.Count; ++i) 75 { 76 var tag = tags[i]; 77 if (tag == null) continue; 78 79 var collider2D = tag.collider2D; 80 if (collider2D == null) continue; 81 if (!collider2D.enabled) continue; 82 83 tag.UpdateCachedMesh(); 84 85 if (tag.cachedMesh == null) 86 continue; 87 88 var colliderBounds = collider2D.bounds; 89 bounds.Encapsulate(colliderBounds.min); 90 bounds.Encapsulate(colliderBounds.max); 91 //bounds.Encapsulate(colliderBounds); 92 93 var buildSource = new NavMeshBuildSource(); 94 buildSource.shape = NavMeshBuildSourceShape.Mesh; 95 buildSource.sourceObject = tag.cachedMesh; 96 if (collider2D.attachedRigidbody) 97 { 98 buildSource.transform = Matrix4x4.TRS(collider2D.transform.position, collider2D.transform.rotation, Vector3.one); 99 } 100 else 101 { 102 buildSource.transform = Matrix4x4.identity; 103 } 104 buildSource.area = tag.area; 105 sources.Add(buildSource); 106 107 } 108 } 109} 110

NavMeshAgent2D版の、マネージャのような空のオブジェクトにアタッチするスクリプト(自作ではありません)

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.AI; 5 6[ExecuteAlways] 7public class NavMeshBuilder2D : MonoBehaviour 8{ 9 public enum UpdateMethod 10 { 11 Manual, 12 Update, 13 FixedUpdate, 14 } 15 16 public bool bakeOnEnable; 17 public UpdateMethod updateMethod; 18 public bool updateAsync; 19 20 Collider2D[] collider2Ds; 21 22 List<NavMeshBuildSource> buildSources = new List<NavMeshBuildSource>(); 23 NavMeshData data; 24 NavMeshDataInstance dataInstance; 25 26 static readonly Quaternion Plane2DRotation = Quaternion.AngleAxis(-90f, Vector3.right); 27 static readonly Quaternion Plane2DRotationInverse = Quaternion.Inverse(Plane2DRotation); 28 29 AsyncOperation buildOperation; 30 31 private void OnEnable() 32 { 33 if (bakeOnEnable) 34 RebuildNavmesh(false); 35 } 36 37 private void OnDisable() 38 { 39 buildOperation = null; 40 dataInstance.Remove(); 41 } 42 43 private void Update() 44 { 45 var shouldUpdate = updateMethod == UpdateMethod.Update; 46#if UNITY_EDITOR 47 shouldUpdate |= (updateMethod == UpdateMethod.FixedUpdate) && !Application.isPlaying; 48#endif 49 if (shouldUpdate) 50 RebuildNavmesh(updateAsync); 51 } 52 53 private void FixedUpdate() 54 { 55 if (updateMethod == UpdateMethod.FixedUpdate) 56 RebuildNavmesh(updateAsync); 57 } 58 59 public void RebuildNavmesh(bool async) 60 { 61 if (async && buildOperation != null && !buildOperation.isDone) 62 return; 63 64 buildOperation = null; 65 66 var totalBounds = new Bounds(); 67 NavMeshSourceTag2D.Collect(ref buildSources, ref totalBounds); 68 var buildSettings = NavMesh.GetSettingsByID(0); 69 var totalBoundsReversed = new Bounds(Plane2DRotationInverse * totalBounds.center, Plane2DRotationInverse * totalBounds.size); // We need to reverse the rotation that's going to be used for baking to get proper bounds 70 var buildBounds = new Bounds(Vector3.zero, Vector3.one * float.MaxValue); //Using enclosing and empty bounds is bugged at the moment - use arbitrarily big one 71 if (!data) 72 { 73 data = NavMeshBuilder.BuildNavMeshData(buildSettings, buildSources, buildBounds, totalBounds.center, Plane2DRotation); 74 } 75 else 76 { 77 if (async) 78 { 79 buildOperation = NavMeshBuilder.UpdateNavMeshDataAsync(data, buildSettings, buildSources, buildBounds); 80 } 81 else 82 { 83 NavMeshBuilder.UpdateNavMeshData(data, buildSettings, buildSources, buildBounds); 84 } 85 } 86 87 dataInstance.Remove(); 88 dataInstance = NavMesh.AddNavMeshData(data); 89 } 90 91 private void OnDrawGizmosSelected() 92 { 93 if (!data) 94 return; 95 96 Gizmos.color = Color.cyan; 97 Gizmos.matrix = Matrix4x4.Rotate(data.rotation); 98 Gizmos.DrawWireCube(data.sourceBounds.center, data.sourceBounds.size); 99 } 100} 101

補足情報(FW/ツールのバージョンなど)

■作業環境
Mac Sierra10.12.6(4GB)
Unity2019.3.f06

■ここまで出来ていること
・プレイヤーキャラクターの移動(AddForce)
・カメラのプレイヤー追従(y軸のみ)
・オブジェクトのランダム座標生成、及びランダムな方向への移動
・加速アイテム実装
・UIによる必殺技カットイン実装

ここまで同じゲームで質問させて頂き、解決に至るご教授を頂いておりますので、
そちらのページも貼っておきます。

加速アイテム実装
アイテムランダム生成、及びランダム移動

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

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

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

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

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

guest

回答2

0

問題点の解決にはなっていないと思いますが、参考程度にご意見させて頂きます。

「2Dタテスクロール競争で、障害物を避けつつ、さらにできれば有益なアイテムを狙いつつ、ゴールまで走るCPU」を実装したいです。NavMeshAgent以外でもいいと思い、「Unity 敵 AI 2D」などで検索して模索中です。もし「作ったことがある」「記事を見かけたことがある」という方がいらっしゃいましたら、お知恵をお借り致したく存じます。

とりあえず、思いつく中での最弱~最強のAIを5段階ぐらい決め、制作してはどうですか?
いきなり最強はかなり難易度が高いと思います。ゲームなのでAIにもレベルがあっても面白いかと...

1段階目 = 雑魚、誰でも勝てる。
2段階目 = ルールさえある程度把握出来れば、勝てる。
3段階目 = ルールの程度把握程度では勝てるか分からない。
4段階目 = ルールを完全把握していれば勝てる。
5段階目 = ルールを完全把握しても勝てるか分からない。

投稿2020/02/10 05:30

stdio

総合スコア3307

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

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

Kageyama_23457

2020/02/10 09:44

stdio様 アドバイスありがとうございます。現在CPUに、障害物やアイテムなどのオブジェクト検知用のオブジェクトを持たせるという形で挑戦中です。
stdio

2020/02/11 00:56

> 障害物やアイテムなどのオブジェクト検知用のオブジェクトを持たせるという形で挑戦中です。 私が以前作ったAIも同じ感じでしたね... 基本NPCってそんな形になるんでしょうね...
guest

0

自己解決

こちら様を参考にスクリプトBを書き換えました。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class NPC_Surface : MonoBehaviour 6{ 7 private Rigidbody2D Ri_Nav,Ri_Surface;//ナビ本体と画像のRB2D 8 private Vector2 Ri_Nav_pos;//ナビの座標 9 10 void Start() 11 { 12 Ri_Surface = GetComponent<Rigidbody2D>(); 13 Ri_Nav = GameObject.Find("Risotto_Nav").GetComponent<Rigidbody2D>();//RB2Dをそれぞれ取得 14 } 15 void Update() 16 { 17 Transform Ri_Nav_transform = Ri_Nav.transform;//ナビのトランスフォームを取得 18 19 Vector3 Ri_Nav_pos = Ri_Nav_transform.position; 20 float x = Ri_Nav_pos.x; 21 float y = Ri_Nav_pos.y; 22 float z = Ri_Nav_pos.z; 23 24 //以下、画像の座標をナビの座標に同期 25 Ri_Surface.transform.position = new Vector3(x, y, z);//単純に「画像の座標=ナビのワールド座標」と記述 26 } 27}

なぜカメラのスクリプトは通ってBはだめだったのか、根本的な理由は理解できていませんが、
当方の目標である「NPCキャラに、2D環境でNavで走らせる」は実装できたので解決とします。

投稿2020/03/30 01:38

Kageyama_23457

総合スコア21

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問