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

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

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

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

Unity3D

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

Unity

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

Q&A

解決済

1回答

1738閲覧

Unityで衝突したものの保持が書き換えられる

teratail-08

総合スコア1

C#

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

Unity3D

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

Unity

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

0グッド

0クリップ

投稿2020/07/27 05:00

編集2020/07/27 08:59

要点

Unityで簡単な壁当てのようなプログラムを作りたいと思い床と壁とボールとプレイヤーのオブジェクトのみでプロジェクトを作りました。
スクリプトはプレイヤーにのみ付いていて移動、ボールと接触したときにボールを持つ、持ってる状態でスペースキー入力で投げるの3つのみの動作です。

タグについてボールにのみBallタグを付けそれ以外はUntaggedになっています。

発生している問題

プレイヤー側で何かにぶつかった判定をOnCollisionEnterでとり、TagがBallのときプレイヤーのhandにCollisionを保持しています。

ボールを掴むところまではできましたが掴んでいる時に壁等のオブジェクトにぶつかるとhandがそのオブジェクトに書き換えられてしまい、ボールは投げられず壁にはついていないRigidbodyが呼ばれてエラーになってしまいます。
MissingComponentException: There is no 'Rigidbody' attached to the "Wall" game object, but a script is trying to access it.

プレイヤーについたスクリプト

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class PlayerControl : MonoBehaviour 6{ 7 public float speed = 5f; 8 public float rotateSpeed = 120f; 9 public float power = 1; 10 private Collision hand =null; 11 12 void FixedUpdate() 13 { 14 15 float h = Input.GetAxis("Horizontal"); 16 float v = Input.GetAxis("Vertical"); 17 18 Vector3 velocity = new Vector3(0, 0, v); 19 20 // キャラクターのローカル空間での方向に変換 21 velocity = transform.TransformDirection(velocity); 22 23 // キャラクターの移動 24 transform.localPosition += velocity * speed * Time.fixedDeltaTime; 25 26 // キャラクターの回転 27 transform.Rotate(0, h * rotateSpeed * Time.fixedDeltaTime, 0); 28 29 30 } 31 32 void OnCollisionEnter(Collision collision) 33 { 34 Debug.Log(collision.gameObject.name); 35 if (collision.gameObject.tag=="Ball" && hand==null) 36 { 37 Debug.Log("catch"); 38 39 hand = collision; 40 hand.transform.parent = transform; 41 hand.collider.isTrigger = true; 42 Rigidbody RB = hand.gameObject.GetComponent<Rigidbody>(); 43 RB.isKinematic = true; 44 hand.transform.localPosition= new Vector3(0.5f, 0, 0.5f); 45 hand.transform.Rotate(0, 0, 0); 46 } 47 } 48 49 // Start is called before the first frame update 50 void Start() 51 { 52 53 } 54 55 // Update is called once per frame 56 void Update() 57 { 58 if (hand != null && Input.GetKeyDown(KeyCode.Space)) 59 { 60 hand.transform.Rotate(0, 0, 0); 61 hand.transform.localPosition = new Vector3(0, 0, 1.5f); 62 hand.collider.isTrigger = false; 63 Rigidbody RB = hand.gameObject.GetComponent<Rigidbody>(); 64 RB.isKinematic = false; 65 RB.AddForce(hand.transform.forward * power); 66 hand.transform.parent = null; 67 Debug.Log(hand.transform.parent); 68 hand = null; 69 Debug.Log("Release"); 70 } 71 } 72}

プレイヤーの移動に関してはこちらのサイトを参考にさせていただきました。

試したこと・わかっていること

ボールを掴んでいる時に壁に触れるとログにcatchと表示されずにhandが書き換わっているのでどこが原因か一切わからないです。

ボール掴み時は常にボールとは接触していますがOnCollisionEnterを利用しているので壁に触れない限り呼ばれません。ログを表示させてみたところボール掴み時に壁に触れた瞬間にhandの中身が書き換わっていてどう手を付ければ良いのかもわかりません。

補足情報

OS:Windows 10
Ver:2019.4.4f1 Personal

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

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

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

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

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

Y0241-N

2020/07/27 08:36

コードを見る限りでは壁にBallのTagが付いていない限り置き換わる要因はなさそうですね。 ログにcatchと表示されずにhandが書き換わるということは、提示している部分以外でhandを置き換える処理があると思うのですが... スクリプトの有効/無効を切りかえながらどのスクリプトが原因か調べてみてください。
teratail-08

2020/07/27 09:01

ご依頼ありがとうございます。 追記しました。
guest

回答1

0

ベストアンサー

衝突したものの保持

衝突した「オブジェクト」を記憶しておくために Collision を保存(正確には「参照」)してはいけません。collision.gameObject を利用して GameObject を参照(保存)しなければいけません。

Collision は「そのコライダーの衝突・接触情報」であるため、Collision を参照していると衝突があるたびに衝突している GameObject その他(接触している座標など)の情報は変わります。

例えば以下のコンポーネントを動かしてみると、違う(名前の)GameObject に衝突する度に出力される情報が変わることがわかるはずです。

csharp

1using UnityEngine; 2 3public class KeepCollision : MonoBehaviour 4{ 5 Collision m_collision; 6 7 void Update() 8 { 9 Debug.Log(m_collision.gameObject.name); 10 } 11 12 void OnCollisionEnter(Collision collision) 13 { 14 if (m_collision == null) 15 { 16 m_collision = collision; 17 } 18 } 19}

投稿2020/07/27 14:04

編集2020/07/27 14:45
bboydaisuke

総合スコア5275

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

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

teratail-08

2020/07/27 14:40

完全に理解しました。 Collisionの参照はぶつかるたびに変わるためログにcatchが出ずにhandの参照が変わってしまったということですね…参照型について詳しくなったつもりでいました。 わかりやすい説明と例でありがとうございます。非常に助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問