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

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

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

Q&A

解決済

2回答

2192閲覧

(Unity)最も近いオブジェクトの取得について

ssss_grid

総合スコア16

0グッド

0クリップ

投稿2018/10/21 03:38

前提・実現したいこと

一番近いターゲットの方向へ移動。
それを破壊した後、次に近いターゲットへの接近。

ここに質問の内容を詳しく書いてください。
http://beatdjam.hatenablog.com/entry/2014/10/22/032751

上記サイトを参考にして、Unity2Dにて一番近いenemyへ接近するという機能を実装しようとしています。
一匹目のenemyに接近するのはうまくいくのですが、それを破壊した後、次の最も近いenemyへターゲットを移すことができていません。

おそらく、2Dなので敵位置の取得をLookAtの代わりで補っている部分が問題なのだろうとは思うのですが、どうすればうまく修正できるのかがわかりません。

発生している問題・エラーメッセージ

MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.

該当のソースコード

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Ally2 : MonoBehaviour { 6 7 Chara chara; 8 Rigidbody2D rd; 9 private GameObject nearEnemy; 10 private float seachTime = 0; 11 12 IEnumerator Start () { 13 nearEnemy = searchTag(gameObject,"Enemy"); 14 chara = GetComponent<Chara> (); 15 rd = GetComponent<Rigidbody2D> (); 16 17 while (true) { 18 Instantiate (bullet, AttackPos); 19 yield return new WaitForSeconds (AttackDelay); 20 } 21 } 22 23 void Update () { 24 seachTime = Time.deltaTime; 25 if (seachTime >= 1.0f) { 26 nearEnemy = searchTag (gameObject, "Enemy"); 27 seachTime = 0; 28 } 29 // 30 Vector3 diff = (nearEnemy.transform.position - this.transform.position); 31 this.transform.rotation = Quaternion.FromToRotation (Vector3.right,diff); 32 33 var v = new Vector2 (1.0f*Time.deltaTime, rd.velocity.y) * chara.Speed; 34 transform.Translate (v); 35 } 36 37 GameObject searchTag(GameObject nowEnemy,string tagName){ 38 float tmpDis = 0; 39 float nearDis = 0; 40 GameObject targetObj = null; 41 42 foreach (GameObject obs in GameObject.FindGameObjectsWithTag(tagName)) { 43 tmpDis = Vector2.Distance (obs.transform.position, nowEnemy.transform.position); 44 45 if (nearDis == 0 || nearDis > tmpDis) { 46 nearDis = tmpDis; 47 targetObj = obs; 48 } 49 } 50 return targetObj; 51 } 52}

試したこと

LookAtの代わりは下記サイトを参考にしました。
http://karaagedigital.hatenablog.jp/entry/2016/09/11/192600

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

よろしくお願いします。

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

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

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

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

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

Bongo

2018/10/21 08:41

オリジナルのコードでは「searchTime += Time.deltaTime;」となっている部分を「seachTime = Time.deltaTime;」としたのは意図があってのことでしょうか?ここが書き換えられていると「1秒おきに一番近い敵を再検索」という動きにならなくなりそうですが...
ssss_grid

2018/10/21 10:17

あーそこでしたか!ありがとうございます。見落としでした。ただ、倒すたびに新たにターゲットを見つけるまでの一瞬だけ同じ箇所にnullのエラーが出ます(止まったりはしないですが)
guest

回答2

0

※エラーの箇所を誤解していたので、回答を差し替えました。

回答の前に1点指摘を。

C#

1GameObject searchTag(GameObject nowEnemy,string tagName){ // nowEnemyではなく、 2GameObject searchTag(GameObject player,string tagName){ // playerでは?

で、本題です。

エラー箇所はVector3 diff = (nearEnemy.transform.position - this.transform.position);の方でした。

nearEnemyがどの時点でnullになるかデバッガで確認し、その原因を調べたり考えたりしてみてください。

予想ですがおそらく、敵機が0になった結果、searchTagメソッドのGameObject.FindGameObjectsWithTag(tagName)の部分で取得できる敵機がなく、targetObjが初期値nullのままになってしまったのかなと思います。

もしそうであれば、敵機がいない場合はそちらを向かないよう、if文で制御すればいいかと思います。

投稿2018/10/21 04:24

編集2018/10/21 08:08
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

ssss_grid

2018/10/21 07:32

ご回答ありがとうございます! そうですねエラーをきちんと把握できていませんでした。 エラー箇所は Vector3 diff = (nearEnemy.transform.position - this.transform.position); の方でした。すいません。 nearEnemyの場合でも、上記エラー箇所の上にif文でnullの時には仮の敵を置く処理がよいのでしょうか。
退会済みユーザー

退会済みユーザー

2018/10/21 08:47 編集

回答を差し替えました
guest

0

自己解決

Bongo様のご指摘の通り
「seachTime = Time.deltaTime;」
「searchTime += Time.deltaTime;」
私の見落としでした。
ただ、倒すたびに新たにターゲットを見つけるまでの一瞬だけ同じ箇所にnullのエラーが出ます(止まったりはしないですが、、、)

投稿2018/10/21 10:20

ssss_grid

総合スコア16

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

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

Bongo

2018/10/21 21:22

では、敵の再検索を行う条件を「if (nearEnemy == null || seachTime >= 1.0f) { ...」としてみてはいかがでしょうか? これなら、1秒経過した場合に加えて、nearEnemyが破壊済みの場合にも敵の再検索が行われるようになるかと思います。 さらに最後の敵を破壊した後には、ppnさんからご指摘のあった「敵が見つからずsearchTagがnullを返す」という状況になるでしょうから、ppnさんの案も折衷して、回転部分にさらにnullチェックを追加するのがよさそうです。 if (nearEnemy == null) { Vector3 diff = (nearEnemy.transform.position - this.transform.position); this.transform.rotation = Quaternion.FromToRotation (Vector3.right,diff); } ※余談ですが、「破壊済みのオブジェクトを参照する変数をnullと比較するとtrueになる」という挙動はUnityEngine.Object特有でして、??演算子を使う場合など「本当のnull」と「破壊済みnull」の違いを考慮する必要のある状況もありますのでご注意ください。 参考:「Unityのnullはnullじゃないかもしれない」(https://qiita.com/satanabe1@github/items/e896303859be5d42c188 )
ssss_grid

2018/10/22 01:22

ありがとうございます! 「if (nearEnemy == null || seachTime >= 1.0f) { ...」で一瞬のエラーは消えました。 「本当のnull」と「破壊済みnull」の違いを考慮する必要のある状況があるのですね。勉強になります。ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問