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

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

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

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

Q&A

解決済

3回答

3283閲覧

unityにて体力0になったら、FixedJointで繋いだ子同士オブジェクトを解除する場合について

urusu2019

総合スコア19

Unity3D

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

0グッド

0クリップ

投稿2019/01/05 17:44

以下のコードだとエラーで動きません。

using System.Collections; using System.Collections.Generic; using UnityEngine; public class Health5 : MonoBehaviour { public int Health = 10; public int MaximumHealth = 10; private void OnCollisionEnter(Collision collision) { this.Damage(1); } public void Damage(int value) { this.Health = Mathf.Clamp(this.Health - value, 0, this.MaximumHealth); // ダメージ表現 var ratio = (float)this.Health / this.MaximumHealth; this.GetComponent<Renderer>().material.color = new Color(1.0f, ratio, ratio); if (this.Health > 0) { return; } var FixedJoint = this.GetComponent<FixedJoint>(); if (FixedJoint == null) { return; } FixedJoint.enabled = false; } }

以下のコードだとエラーは無いのですが、パージされません。

using System.Collections; using System.Collections.Generic; using UnityEngine; public class Health1 : MonoBehaviour { public const int maxHealth = 10; public int currentHealth = maxHealth; public void TakeDamage(int amount) { currentHealth -= amount; if (currentHealth <= 0) { //コンポーネントを取得 FixedJoint component = this.gameObject.GetComponent<FixedJoint>(); // 指定したコンポーネントを削除 Destroy(component); } } }

どのような問題があるのか教えて下さい。

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

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

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

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

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

guest

回答3

0

ベストアンサー

FixedJointは(それだけでなく、他のJointも)、enabledプロパティを持っていないためオン・オフによって有効・無効を切り替えることはできないようですね。

第1のコードについては、第2のコードでやっているのと同様にDestroyでジョイントを破壊してやればよさそうです。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Health5 : MonoBehaviour 6{ 7 public int Health = 10; 8 public int MaximumHealth = 10; 9 10 private void OnCollisionEnter(Collision collision) 11 { 12 this.Damage(1); 13 } 14 15 public void Damage(int value) 16 { 17 this.Health = Mathf.Clamp(this.Health - value, 0, this.MaximumHealth); 18 19 // ダメージ表現 20 var ratio = (float)this.Health / this.MaximumHealth; 21 this.GetComponent<Renderer>().material.color = new Color(1.0f, ratio, ratio); 22 23 if (this.Health > 0) 24 { 25 return; 26 } 27 28 var FixedJoint = this.GetComponent<FixedJoint>(); 29 if (FixedJoint == null) 30 { 31 return; 32 } 33 34 // FixedJoint.enabled = false; // ここを... 35 Destroy(FixedJoint); // こちらに変える 36 } 37}

第2のコードには特に問題はなさそうに思えますね...他の部分にトラブルがあるんじゃんないでしょうか?
例えば下記のようにコンソールにメッセージを表示させると...

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Health1 : MonoBehaviour 6{ 7 public const int maxHealth = 10; 8 public int currentHealth = maxHealth; 9 10 public void TakeDamage(int amount) 11 { 12 currentHealth -= amount; 13 14 Debug.Log($"ダメージを受けた:({currentHealth}/{maxHealth})"); 15 16 if (currentHealth <= 0) 17 { 18 19 //コンポーネントを取得 20 FixedJoint component = this.gameObject.GetComponent<FixedJoint>(); 21 22 if (component == null) 23 { 24 Debug.Log("ジョイント取得に失敗"); 25 } 26 else 27 { 28 Debug.Log("ジョイントを破壊"); 29 } 30 31 // 指定したコンポーネントを削除 32 Destroy(component); 33 34 } 35 } 36}

もし1点ずつダメージを与えた場合、「ダメージを受けた:(9/10)」「ダメージを受けた:(8/10)」...とどんどん体力が減少し、最後に「ダメージを受けた:(0/10)」「ジョイントを破壊」と表示されるでしょうか?

もし「ダメージを受けた」メッセージすら表示されないようでしたら、TakeDamageを正しく実行できていないと言えるでしょう。
TakeDamageは正しく実行されているけれども、最後に「ジョイント取得に失敗」と出るようでしたら、this.gameObject.GetComponent<FixedJoint>()でジョイントが見つからなかったということになりますね。ジョイントがすでに破壊されているか、あるいはジョイントがアタッチされているオブジェクトとHealth1をアタッチしたオブジェクトが異なっている...といったケースが考えられます。

投稿2019/01/05 20:58

Bongo

総合スコア10807

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

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

urusu2019

2019/01/06 15:40

回答ありがとうございます。 以前聞き忘れた質問ですみません。 以下のコードにてオブジェクトにアタッチするとダメージの蓄積により色が変わってしまう現象があります。 this.GetComponent<Renderer>().material.color = new Color(1.0f, ratio, ratio); 上記のコードを削除すると解除されるようですが、削除は問題無いのでしょうか? using System.Collections; using System.Collections.Generic; using UnityEngine; public class Health5 : MonoBehaviour { public int Health = 10; public int MaximumHealth = 10; private void OnCollisionEnter(Collision collision) { this.Damage(1); } public void Damage(int value) { this.Health = Mathf.Clamp(this.Health - value, 0, this.MaximumHealth); // ダメージ表現 var ratio = (float)this.Health / this.MaximumHealth; this.GetComponent<Renderer>().material.color = new Color(1.0f, ratio, ratio); if (this.Health > 0) { return; } GetComponent<Rigidbody>().constraints = RigidbodyConstraints.None; } }
Bongo

2019/01/06 15:51

ええそうです。その部分と、ratioもそこでしか使っていないので削除できます。「// ダメージ表現」とコメントを付けた直後の2行を両方とも削除してしまってください。 以前投稿した回答では、ダメージが蓄積していることを画面上で確認するために色を付けていたのですが、動作の上では消しても問題はありません。
urusu2019

2019/01/07 16:37

そうだったのですね。 気遣いありがとうございます。 第2のコードを実行したら、error CS1644: Feature `interpolated strings' cannot be used because it is not part of the C# 4.0 language specification と出ました。 後で設定変更して再起動してみます。 もしかしたらこれが原因で作動しなかったかもしれません。
Bongo

2019/01/07 19:54

スクリプトランタイムのバージョン違いみたいですね。もし設定変更でうまくいかないようでしたら、 Debug.Log($"ダメージを受けた:({currentHealth}/{maxHealth})"); を Debug.LogFormat("ダメージを受けた:({0}/{1})", currentHealth, maxHealth); に変更してみてください。こちらでも同じように動くかと思います。
urusu2019

2019/01/08 19:08

エラーは無くなりましたがコンソールは無反応ですね。 第一のコードは成功しましたが、PCへの負荷や処理速度を考えた場合に第一と第二のコードどちらが有用なのでしょうか?
Bongo

2019/01/08 21:13 編集

弾を受けてもコンソールに何も出ないようでしたら、そもそもTakeDamageが実行されていないっぽいですね... 第1と第2のスクリプトはどちらも大した違いはなく、負荷や速度面で気にするべき点はないように思います。第1のpublic void Damage(int value)と、第2のpublic void TakeDamage(int amount)がダメージを与えるメソッドであり、名前が違うものの、やっていることはほとんど同じです。 第1のコードについてですが、当初私が投稿した際には「おそらく実際のスクリプトでは弾側のスクリプトで衝突を検出し、このオブジェクトのダメージメソッドを呼び出すことになるだろうけども、今回は実験目的なので自分自身で適当に衝突判定してしまえばいいだろう」と考えていました。そのため、第1のコードには... private void OnCollisionEnter(Collision collision) { this.Damage(1); } という風に、自分自身で衝突検出して自分自身のダメージメソッドを実行している部分があります。 一方第2のコードには衝突検出のためのメソッドがありません。別のスクリプトからダメージメソッドを実行することを前提としており、そしてどうやらその部分がうまくいっていないようです。 どこがまずいのか調べるには、弾オブジェクトやこのオブジェクトの構造...どのようなコンポーネントがアタッチされていて、親子関係はこうなっていて...といった詳細と、弾のスクリプトがどうなっているか見てみる必要がありそうですね。
urusu2019

2019/01/10 16:36

弾は普通のSphereで以前教えて頂いたShootingをアタッチしています。 画像を載せました。 弾の当たる対象は鳥みたいなモノです。 これで分かるでしょうか?
Bongo

2019/01/10 22:56 編集

なるほど、これだけ詳しくスクリーンショットを載せていただけますとオブジェクト同士の関係がわかりやすくていいですね。ありがとうございます。 弾に付いている「Bullet」スクリプトは、以前「弾丸によるダメージで体力が0になったらアニメーションを途中で終了しオブジェクトをフリーにしたい場合について。」(https://teratail.com/questions/166516 )のコメント欄にご提示いただいた... using UnityEngine; using System.Collections; public class Bullet : MonoBehaviour { void OnCollisionEnter(Collision collision) { var hit = collision.gameObject; var health = hit.GetComponent<Health>(); if (health != null) { health.TakeDamage(10); } } } でよろしいでしょうか? もしそうだとすると、スクリプトコンポーネントの名前が異なっているために失敗している可能性がありそうです。 下記のようにコンポーネント名を変えるか... using UnityEngine; using System.Collections; public class Bullet : MonoBehaviour { void OnCollisionEnter(Collision collision) { var hit = collision.gameObject; var health = hit.GetComponent<Health1>(); // 「Health」ではなく「Health1」を取得 if (health != null) { health.TakeDamage(10); } } } あるいは別案として、下記のようにコンポーネントを特定せずにTakeDamageメッセージを送信するというのはどうでしょうか? using UnityEngine; using System.Collections; public class Bullet : MonoBehaviour { void OnCollisionEnter(Collision collision) { var hit = collision.gameObject; hit.SendMessage("TakeDamage", 10, SendMessageOptions.DontRequireReceiver); } }
urusu2019

2019/01/13 16:18

上手く作動しました。 様々な兵装を用意しようと思うので、兵装1では5発当てないと破壊出来ないが、兵装2だと1発で貫通する・・・等を考えると重要なコードだと思います。 ありがとうございました。
guest

0

イメージ説明
イメージ説明
イメージ説明
イメージ説明
イメージ説明

投稿2019/01/10 16:36

urusu2019

総合スコア19

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

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

0

イメージ説明

投稿2019/01/10 16:26

urusu2019

総合スコア19

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問