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

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

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

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

Unity

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

Q&A

解決済

1回答

873閲覧

unity2D 衝突時に関数を実行したい

tom_honmono

総合スコア22

C#

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

Unity

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

0グッド

0クリップ

投稿2021/04/11 07:12

wiiのタンクのような、戦車で戦うゲームを作っています。
そのなかで、プレイヤーが見えた瞬間に敵に球を発射してもらいたく、普通の球とは別に見えない球を高速でプレイヤーの座標に発射し、それがヒットしたら普通の球を発射するというふうにしようと考えました。
なのでまず

void OnCollisionEnter2D(Collision2D collision){ Debug.Log("HitTest"); 普通の球を発射する関数; Destroy(this.gameObject);

としてみましたが、普通の球を発射する関数が void update 内にある為、呼び出すことができませんでした。void updateの中でstaticやpublicがつけれないのでこの方法は一度諦めました(できるならご教授ください)

その次に、衝突時に変数を代入して、update内のif文でその変数を感知したら普通の球を発射するものを考えました

void OnCollisionEnter2D(Collision2D collision){ Debug.Log("HitTest"); AttackTest =1; Destroy(this.gameObject); } void update(){ void EnemyBall(){ // 弾(ゲームオブジェクト)の生成 GameObject clone = Instantiate(ball, transform.position, Quaternion.identity); // クリックした座標の取得(スクリーン座標からワールド座標に変換) Vector3 mouseWorldPos = tmp; // 向きの生成(Z成分の除去と正規化) Vector3 shotForward = Vector3.Scale((mouseWorldPos - transform.position), new Vector3(1, 1, 0)).normalized; // 弾に速度を与える clone.GetComponent<Rigidbody2D>().velocity = shotForward * speed; } if(AttackTest == 1){ EnemyBall(); AttackTest = 0; } }

しかしこれだと、なんか反応しません。おそらくAttackTestに数を代入しているのが反映されていません。
どうすれば解決できそうでしょうか、 よろしくお願いします。
最後に(試行錯誤中でぐちゃぐちゃですが)コード全体を貼ります

using System.Collections; using System.Collections.Generic; using UnityEngine; public class TestBall : MonoBehaviour { public GameObject testtestBall; GameObject gameobject; float speed2; public float span2 = 0.5f; private float testtime = 0f; public GameObject ball; float speed; public int AttackTest; void OnCollisionEnter2D(Collision2D collision){ Debug.Log("HitTest"); AttackTest =1; Destroy(this.gameObject); } // Start is called before the first frame update void Start() { speed = 4.0f; speed2 = 100.0f; gameobject = GameObject.Find("Enemy"); AttackTest = 0; } // Update is called once per frame void Update() { Vector3 tmp = GameObject.Find("HeavyHullD").transform.position; testtime += Time.deltaTime; if(testtime > span2){ testBall(); testtime = 0f; } void testBall(){ GameObject clone = Instantiate(testtestBall, transform.position, Quaternion.identity); Vector3 mouseWorldPos2 = tmp; Vector3 shotForwards = Vector3.Scale((mouseWorldPos2 - transform.position), new Vector3(1, 1, 0)).normalized; clone.GetComponent<Rigidbody2D>().velocity = shotForwards * speed2; } void EnemyBall(){ // 弾(ゲームオブジェクト)の生成 GameObject clone = Instantiate(ball, transform.position, Quaternion.identity); // クリックした座標の取得(スクリーン座標からワールド座標に変換) Vector3 mouseWorldPos = tmp; // 向きの生成(Z成分の除去と正規化) Vector3 shotForward = Vector3.Scale((mouseWorldPos - transform.position), new Vector3(1, 1, 0)).normalized; // 弾に速度を与える clone.GetComponent<Rigidbody2D>().velocity = shotForward * speed; } if(AttackTest == 1){ EnemyBall(); AttackTest = 0; } } }

もともとは下のEnemyMoveスクリプトで3秒に一回普通の球を発射していました。
それを変更したく、ここにある普通の球の発射の関数EnemyBallを上記スクリプトに移動しました。(移動した理由は、上記スクリプトからこのスクリプトの関数の実行に手間取ったからです)

using System.Collections; using System.Collections.Generic; using UnityEngine; public class EnemyMove : MonoBehaviour { public GameObject ball; float speed; public float span = 3f; public float currentTime = 0f;// // Start is called before the first frame update void Start() { speed = 4.0f; } // Update is called once per frame void Update() { Vector3 tmp = GameObject.Find("HeavyHullD").transform.position; currentTime += Time.deltaTime; //if(currentTime > span){ // EnemyBall(); // currentTime = 0f; //} if (Input.GetMouseButtonDown(0)) { } void EnemyBall(){ // 弾(ゲームオブジェクト)の生成 GameObject clone = Instantiate(ball, transform.position, Quaternion.identity); // クリックした座標の取得(スクリーン座標からワールド座標に変換) Vector3 mouseWorldPos = tmp; // 向きの生成(Z成分の除去と正規化) Vector3 shotForward = Vector3.Scale((mouseWorldPos - transform.position), new Vector3(1, 1, 0)).normalized; // 弾に速度を与える clone.GetComponent<Rigidbody2D>().velocity = shotForward * speed; } } void OnCollisionEnter2D(Collision2D collision){ if(collision.gameObject.tag == "Ball"){ Debug.Log("hitEnemy"); Destroy(this.gameObject); } } }

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

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

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

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

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

tsuki01

2021/04/11 14:58 編集

実際に検証していないのでコメントで失礼します。 OnCollisionEnter2Dの中で、スクリプトをアタッチしたGameObjectをDestroyしているのが大きな原因てことはないでしょうか。 スクリプトをアタッチしたGameObjectを削除してしまうと、スクリプトも途中で実行されなくなります。 一旦、Destroy部分をコメントアウトしてみたり、ログ出力を追加してどこまで処理が進んでいるか確認してみるのはいかがでしょうか。 ※その他気になる点 関数の中に関数(Update内でEnemyBall定義など)は普通は実装しない気がします。 関数の外に出せば、懸念している「void updateの中でstaticやpublicがつけれないので」という問題も解決できるのではないでしょうか。 (何かを参考に実装していたら申し訳ありません)
tom_honmono

2021/04/11 15:25

丁寧な返信本当にありがとうございます。 試しにDestroyをコメントアウトしてみましたが、消えないだけで変わりませんでした。一応球ではなく敵の戦車本体にアタッチしてみてもうまくいきませんでした。 UPdate内で実装したのは適当なサイトを参考にしたのですが、たしかに外に出せれば解決しそうです。ただそこまでC#に慣れていないので、何回か挑戦していますが外に出してうまく動作してくれなくて困っています また何か気づいたことがあれば教えてください
tsuki01

2021/04/13 13:55 編集

返信遅れました。 > 試しにDestroyをコメントアウトしてみましたが、消えないだけで変わりませんでした。 ↑こちらですが、「EnemyBall()関数が呼べなかった」という認識で大丈夫でしょうか。 「OnCollisionEnter2D」の関数が正常に呼ばれてれば、現在の処理でもEnemyBall関数自体は呼べるのかなと想定していました。(処理の書き方は一旦置いておいて、関数呼び出し自体は動く想定であった) ※こちらで、試しにコードをコピペしてAttackTest変数を"1"にしたら、EnemyBall関数自体は呼ばれたのですが、他に違う箇所があるのかもしれません。
tom_honmono

2021/04/14 07:48

自己解決できました!!一緒に考えてくださり本当にありがとうございました!!!
guest

回答1

0

自己解決

public int AttackTestを、
static int AttackTestにしたらちゃんと数字が代入されるようになり求める挙動になりました、、、、
解決したけど簡単なことに時間を使ってしまった、、、泣

投稿2021/04/14 07:49

tom_honmono

総合スコア22

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

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

fiveHundred

2021/04/14 08:09

失礼しますが、本当に理解している上でstaticを使っていますか? staticは「クラスに族する変数(≒どのオブジェクトにおいても共通の変数)」という意味なので、publicと同列に扱うものではありません。 そのため、このように書き換えてしまうと、以下のようになりますが、これは本当に意図した挙動なのでしょうか? 1. TestBall(A)が生成される 2. TestBall(A)のOnCollisionEnter2D()内でAttackTestを1にする 3. 直後にTestBall(A)をDestroy()で破棄する 4. TestBall(B)が生成される 5. TestBall(B)はTestBall(A)と別物だが、「2.」によってAttackTestが1になっているので、(TestBall(B)自身の接触の有無に関わらず)TestBall(B)から発射される
fiveHundred

2021/04/14 08:17

もしくは、最初からTestBall(A)とTestBall(B)が両方存在していて、片方が接触された際にもう片方から発射の処理がされる、といった感じになっているかもしれません。 いずれにしても、TestBall(A)が発射の処理を行っていないため、TestBallが1つしか存在しない(それ以降も生成されない)場合は動作しないことになるのではないかと思います。
tom_honmono

2021/04/14 16:03

試しに壁を置いてみたら挙動が変でした。ご指摘くださりありがとうございます。他の方法を考えてみます。はぁ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問