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

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

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

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

Unity

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

Q&A

1回答

4127閲覧

Unity 誘導弾を自然な挙動にしたい

asd1

総合スコア0

C#

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

Unity

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

0グッド

0クリップ

投稿2020/07/18 16:33

編集2020/07/18 16:45

前提・実現したいこと

以下のURLを参考にして、2Dゲームで誘導弾を実装しました。
ターゲットである"Enemy"のタグのオブジェクトに向かって理想的な動きはするのですが、ターゲットがなくなった(=null)際にその時点での座標で停止し、Rigidbody2Dの重力で落ちるだけの挙動になります。
そうではなく、
1,ターゲットのいない時は一定の向きに飛ぶ
2,ターゲットが来たら向かっていく
3,ターゲットがなくなった際に現在動いている方向に直進して抜けていく
というような自然な動きで弾を飛ばしたいのですが改善案はありますでしょうか?

https://www.slideshare.net/UnityTechnologiesJapan/unite-2018-tokyo/UnityTechnologiesJapan/unite-2018-tokyo

該当のソースコード

C#

1void Start() 2 { 3 position = transform.position; 4 rigid = GetComponent<Rigidbody2D>(); 5 target = GameObject.FindWithTag("Enemy"); 6 } 7void Update() 8 { 9 acceleration = new Vector3(5f,15f,0); //初速度 10 Tracking(); 11 } 12 13 void Tracking() 14 { 15 var diff = target.transform.position - transform.position; //ターゲットとの距離 16 17 acceleration += (diff - velocity * period) * 2f / (period * period); //加速度a = 2(d-vt) / t*t 18 19 period -= Time.deltaTime; //period秒後に着弾 20 if (period < 0f) 21 { 22 return; 23 } 24 25 velocity += acceleration * Time.deltaTime; //v = at 26 position += velocity * Time.deltaTime; //d = vt 27 transform.position = position; 28 }

試したこと

Tracking();内の移動処理
{position += velocity * Time.deltaTime; //d = vt
transform.position = position;}
この部分を非アクティブにして
rigid.MovePosition(transform.position + velocity * Time.deltaTime);
こちらをFixedUpdate()で入力したところマシな動きにはなったが射出した弾の何発かが急に謎の方向に吹っ飛んで行ったりした。

個人的な見解として、target = nullの時、diff の値がおかしくなり、accelerationがおかしくなり、という流れは読めるのですが改善策が思いつかないので質問させていただきました。

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

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

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

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

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

guest

回答1

0

以下は読む人のためにも守って欲しいですね。

  1. 宣言のない変数があるコードは示さない
  2. インデントの壊れたコードは示さない

csharp

1using UnityEngine; 2 3public class Homing : MonoBehaviour 4{ 5 Vector3 position; 6 Rigidbody2D rigid; 7 GameObject target; 8 Vector3 acceleration; 9 float period = 3f; 10 Vector3 velocity; 11 12 void Start() 13 { 14 position = transform.position; 15 rigid = GetComponent<Rigidbody2D>(); 16 target = GameObject.FindWithTag("Enemy"); 17 velocity = new Vector3(3f, 5f, 0); // 初速 18 } 19 20 void Update() 21 { 22 acceleration = new Vector3(5f, 15f, 0); //初速度 23 Tracking(); 24 } 25 26 void Tracking() 27 { 28 if (target && target.activeSelf) 29 { 30 var diff = target.transform.position - transform.position; //ターゲットとの距離 31 32 acceleration += (diff - velocity * period) * 2f / (period * period); //加速度a = 2(d-vt) / t*t 33 34 period -= Time.deltaTime; //period秒後に着弾 35 if (period < 0f) 36 { 37 return; 38 } 39 velocity += acceleration * Time.deltaTime; //v = at 40 } 41 else if (!target) 42 { 43 target = GameObject.FindWithTag("Enemy"); 44 } 45 46 position += velocity * Time.deltaTime; //d = vt 47 transform.position = position; 48 } 49}

物理エンジンをまったく使わずにコーディングで強引に挙動を実装していますが、物理エンジンを適切に使えばこういった処理、および目標物を失った時の挙動などは簡単に制御できるので、物理エンジン (Rigidbody) について学び始めた方がよいと思います。

投稿2020/07/18 17:50

編集2020/07/18 18:34
bboydaisuke

総合スコア5275

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

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

asd1

2020/07/19 04:25

ご回答頂き有難うございます。 質問するにあたり情報が不充分だった点に関してお詫び申し上げます。 誘導弾に関して調べるとこのコードが多くみられるので、この手法でも求める動きは実現できるものと考えておりましたが、仰る通り一度手を止めて物理エンジンに限らずインプットの時間を設けようと思います。 有難うございました。
bboydaisuke

2020/07/19 07:24 編集

Velocity を計算したのなら、それを Rigidbody2D.velocity に入れればオブジェクトはその速度ベクトルで動きます。その速度で動いた座標を計算してあげる必要はありません。また Rigidbody2D には Gravity Scale というプロパティがあり、これにより重力の影響をどれくらい受けるかを制御できます。0 にすると重力の影響を受けなくなります。 これらを組み合わせれば、オブジェクトは放っておくだけで等速直線運動をします。Position を計算してしまうと、そうはいかなくなってしまいます。
bboydaisuke

2020/07/19 10:13 編集

また、Position を計算して代入するということは「瞬間移動を繰り返す」ことになり、物理エンジンによる当たり判定ができなくなります。つまりコライダーをすり抜けたり OnCollisionEnter2D や OnTriggerEnter2D などを使って当たり判定ができなくなってしまうので、それを踏まえた実装をする必要があります。Rigidbody を使った移動をすれば、確実に(といってもあまりに高速だとすり抜けますが)当たり判定を発生させることができます。
bboydaisuke

2020/07/19 07:25

とりあえず私の示したコードで質問に書かれている問題は解決できると思います。
asd1

2020/07/19 09:45

返信が遅れてしまい申し訳ありません、動作確認、修正作業を行っておりました。 ご提示いただいたコードで質問内容に関してかなり改善できそうです。 あとは数値の調整などの細かい修正で形になると思います、有難うございます。 ただ、bboydaisuke様も再三仰られている通り、今回の場合は可能なら物理エンジンで実装すべきだった気がしますので、Rigidbody2Dでの実装もこれからまた考えようと思います。 bboydaisuke様、この度は貴重なお時間を頂き有難うございました。
bboydaisuke

2020/07/19 09:50

そしたらこの質問はまだ回答受付中になってるので、解決済みにしといてくださいね~
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問