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

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

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

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

Unity3D

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

Unity

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

Q&A

解決済

2回答

2061閲覧

Unityで複数のオブジェクトから1つのオブジェクトを選んで追尾する方法

saba0592

総合スコア3

C#

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

Unity3D

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

Unity

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

0グッド

0クリップ

投稿2020/07/12 02:14

前提・実現したいこと

初投稿です。プレハブによって複数配置されたオブジェクトを検知し、その中から1つを選んで追尾するエージェントを作りたいです。追尾していたオブジェクトが消滅した場合は、先ほど検知した別のオブジェクトにターゲットを変えて同じように追尾してほしいです。

該当のソースコード

#####エージェント制御のコード

c#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.AI; 5public class Agent : MonoBehaviour 6{ 7 private int Mode;//エージェントのモード 8 private float attackInterval = 1f;//攻撃の間隔 9 private float lastAttackTime;//最後に攻撃した時間 10 public Transform reimu;//霊夢(プレイヤー) 11 public Transform marisa;//魔理沙(エージェント) 12 private GameObject reimuTower;//今回ターゲットにしたいオブジェクト 13 private NavMeshAgent agent;//エージェント 14 MarisaAttack attack;//攻撃スクリプト 15 16 // Start is called before the first frame update 17 void Start() 18 { 19 //いろいろ取得 20 agent = GetComponent<NavMeshAgent>(); 21 reimuTower = GameObject.FindGameObjectWithTag("ReimuTower"); 22 attack = GetComponentInChildren<MarisaAttack>(); 23 24 //1秒ごとに下記のAI動作を実行 25 InvokeRepeating("AISystem", 0, 1.0f); 26 } 27 28 // Update is called once per frame 29 void AISystem() 30 { 31 //魔理沙とターゲットオブジェクトの距離 32 float distance1 = Vector3.Distance(marisa.position, reimuTower.transform.position); 33 34 //魔理沙と霊夢の距離 35 float distance2 = Vector3.Distance(marisa.position, reimu.transform.position); 36 37 if (10 < distance1)//ターゲットとの距離が10より大きい時 38 { 39 Mode = 0; 40 } 41 42 if (5 < distance2 && distance1 <= 10)//霊夢との距離が5より大きく、ターゲットとの距離が10以下の時 43 { 44 Mode = 1; 45 } 46 47 if (distance2 <= 5)//霊夢との距離が5以下の時 48 { 49 Mode = 2; 50 } 51 52 switch (Mode) 53 { 54 55 case 0: 56 57 //ターゲットに向かう 58 agent.destination = reimuTower.transform.position; 59 break; 60 61 case 1: 62 63 //ターゲットの方を向く 64 Quaternion targetRotation = Quaternion.LookRotation(reimuTower.transform.position - transform.position); 65 transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 1f); 66 67 //ターゲットに向かう 68 agent.destination = reimuTower.transform.position; 69 70 //ターゲットとの距離が2以下、且つ最後に攻撃した時間から1秒以上経っている時 71 if (distance1 <= 2 && Time.time > lastAttackTime + attackInterval) 72 { 73 attack.Attack1();//攻撃 74 lastAttackTime = Time.time;//最後に攻撃した時間を更新 75 } 76 break; 77 78 case 2: 79 //霊夢に向かう 80 agent.destination = reimu.transform.position; 81 82 //霊夢との距離が2以下、且つ最後に攻撃した時間から1秒以上経っている時 83 if (distance2 <= 2 && Time.time > lastAttackTime + attackInterval) 84 { 85 attack.Attack1();//攻撃 86 lastAttackTime = Time.time;//最後に攻撃した時間を更新 87 } 88 break; 89 } 90 } 91} 92

#####プレハブ配置のコード

c#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class TowerInit : MonoBehaviour 6{ 7 public GameObject reimuTowerPrefab;//味方タワー(今回のターゲット) 8 public GameObject reimuTowers;//味方タワーを格納する空オブジェクト 9 public GameObject marisaTowerPrefab;//敵タワー 10 public GameObject marisaTowers;//敵タワーを格納する空オブジェクト 11 12 void Awake() 13 { 14 ReimuSetUp(16.54f, 21.5f, 15f); 15 ReimuSetUp(7f, 21.5f, 43.5f); 16 ReimuSetUp(30f, 21.5f, 21.5f); 17 ReimuSetUp(8f, 20.5f, 31f); 18 ReimuSetUp(31f, 20.5f, 8f); 19 MarisaSetUp(35f, 21.5f, 35f); 20 MarisaSetUp(20.5f, 21.5f, 30f); 21 MarisaSetUp(43f, 21.5f, 8f); 22 MarisaSetUp(42f, 20.5f, 19f); 23 MarisaSetUp(18f, 20.5f, 43f); 24 } 25 26 //味方タワーの配置メソッド 27 void ReimuSetUp(float x, float y, float z) 28 { 29 GameObject r = Instantiate(reimuTowerPrefab, reimuTowers.transform); 30 r.transform.position = new Vector3(x, y, z); 31 } 32 33 //敵タワーの配置メソッド 34 void MarisaSetUp(float x, float y, float z) 35 { 36 GameObject r = Instantiate(marisaTowerPrefab, marisaTowers.transform); 37 r.transform.position = new Vector3(x, y, z); 38 } 39}

試したこと

  • Updateメソッドの中でFindGameObjectTagを使って検知すると最初に検知したオブジェクトが消滅すると追尾をやめてしまいます。また、どれだけ再生し直しても複数ある中の特定の同じオブジェクトしか追尾しません。
  • FindGameObjectsTagは配列なので、取得してから特定の1つのオブジェクトをターゲットにする方法がわかりません。

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

Unity Version 2019.4.1f1 Personal

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

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

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

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

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

guest

回答2

0

ベストアンサー

Updateメソッドの中でFindGameObjectTagを使って検知すると最初に検知したオブジェクトが消滅すると追尾をやめてしまいます

AISystemの最初に現在のターゲットの存在をチェックし、存在しなければ(消滅していれば)別のターゲットを再設定する処理をいれるとどうでしょう。

どれだけ再生し直しても複数ある中の特定の同じオブジェクトしか追尾しません。

ターゲット郡の配列を取得し、その中からランダムで選択する仕組みを入れるとどうでしょう。
また、その後「選び直す」という処置を考えると、取得した配列をシャッフルして保存しておき、上から順々にターゲットとして設定していくと無駄が少ないかと思います。

FindGameObjectsTagは配列なので、取得してから特定の1つのオブジェクトをターゲットにする方法がわかりません。

配列から取り出したい要素を指定するだけです。
https://cprogram.net/c-sharp-array-element-get/

GameObject[] towers = GameObject.FindGameObjectsWithTag("ReimuTower"); reimuTower = towers[0]; //配列の最初の要素をターゲットに設定。

また、「選び直す」操作に加えて「全て消滅したらどうするか?」という処理も用意しておく必要がありそうです。

投稿2020/07/12 03:29

編集2020/07/12 03:29
Kapustin

総合スコア1186

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

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

saba0592

2020/07/12 06:07

回答の方法で試したら理想通りの動きをしてくれるようになりました。ありがとうございます。
guest

0

先ほど検知した別のオブジェクト

これをコンピュータに「わかるように」教えてあげる必要があります。
今のところ、target が消えた時どうするのか、その時どういう条件で次に追尾したいオブジェクトを探すのか、そして次に探したいオブジェクトはこれだと Navmesh Agent に教えてあげる処理などがありませんね。

投稿2020/07/12 02:45

bboydaisuke

総合スコア5275

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

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

saba0592

2020/07/12 06:08

確かにターゲットがなくなった際のコードがありませんでした。次からは気をつけます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問