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

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

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

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

UI

UIはUser Interfaceの略であり、人間がコンピュータとやりとりをするためのシステムです。

Unity3D

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

Unity

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

Q&A

解決済

2回答

1767閲覧

Unityの回復をUIに反映させたい

tr1996

総合スコア1

C#

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

UI

UIはUser Interfaceの略であり、人間がコンピュータとやりとりをするためのシステムです。

Unity3D

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

Unity

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

0グッド

0クリップ

投稿2021/12/23 14:26

編集2021/12/24 11:31

前提・実現したいこと

UnityのチュートリアルのTankに回復アイテムを付けたいです。
触れたら最大値まで回復させたいです。

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

アイテムに触れたらアイテムは消えるのですが、回復をTankのHPのUIに反映させることができません。

自分で追加したスクリプト using System.Collections; using System.Collections.Generic; using UnityEngine; public class HPItem : MonoBehaviour { void OnCollisionEnter(Collision collision) { if (collision.gameObject.tag == "Player") { Destroy(gameObject); } } }
チュートリアルのスクリプト using UnityEngine; using UnityEngine.UI; public class TankHealth : MonoBehaviour { public float m_StartingHealth = 100f; public Slider m_Slider; public Image m_FillImage; public Color m_FullHealthColor = Color.green; public Color m_ZeroHealthColor = Color.red; public GameObject m_ExplosionPrefab; private AudioSource m_ExplosionAudio; private ParticleSystem m_ExplosionParticles; public float m_CurrentHealth; private bool m_Dead; //戦闘不能 private void Awake() //ゲーム開始 { m_ExplosionParticles = Instantiate(m_ExplosionPrefab).GetComponent<ParticleSystem>(); m_ExplosionAudio = m_ExplosionParticles.GetComponent<AudioSource>(); m_ExplosionParticles.gameObject.SetActive(false); } private void OnEnable() // 生き返る時 { m_CurrentHealth = m_StartingHealth; //HPMaxにする m_Dead = false; //死んでない SetHealthUI(); } public void TakeDamage(float amount) { // Adjust the tank's current health, update the UI based on the new health and check whether or not the tank is dead. m_CurrentHealth -= amount; //←ここをm_CurrentHealth += amount;で追加したり SetHealthUI(); //UIの更新 if (m_CurrentHealth <= 0f && !m_Dead) //←ここでelseを追加したりしました { OnDeath(); } } private void SetHealthUI() //スライダーのリセット { // Adjust the value and colour of the slider. m_Slider.value = m_CurrentHealth; m_FillImage.color = Color.Lerp(m_ZeroHealthColor, m_FullHealthColor, m_CurrentHealth / m_StartingHealth); } private void OnDeath() //HPが0になった { // Play the effects for the death of the tank and deactivate it. m_Dead = true; m_ExplosionParticles.transform.position = transform.position; m_ExplosionParticles.gameObject.SetActive(true); m_ExplosionParticles.Play(); m_ExplosionAudio.Play(); gameObject.SetActive(false); } }
チュートリアルのスクリプト using UnityEngine; public class ShellExplosion : MonoBehaviour { public LayerMask m_TankMask; public ParticleSystem m_ExplosionParticles; public AudioSource m_ExplosionAudio; public float m_MaxDamage = 100f; public float m_ExplosionForce = 1000f; public float m_MaxLifeTime = 2f; public float m_ExplosionRadius = 5f; private void Start() { Destroy(gameObject, m_MaxLifeTime); } private void OnTriggerEnter(Collider other) { // Find all the tanks in an area around the shell and damage them. Collider[] colliders = Physics.OverlapSphere(transform.position, m_ExplosionRadius, m_TankMask); for (int i = 0; i < colliders.Length; i++) { Rigidbody targetRigidbody = colliders[i].GetComponent<Rigidbody>(); if (!targetRigidbody) continue; targetRigidbody.AddExplosionForce(m_ExplosionForce, transform.position, m_ExplosionRadius); TankHealth targetHealth = targetRigidbody.GetComponent<TankHealth>(); if (!targetHealth) continue; float damage = CalculateDamage(targetRigidbody.position); targetHealth.TakeDamage(damage); } m_ExplosionParticles.transform.parent = null; m_ExplosionParticles.Play(); m_ExplosionAudio.Play(); Destroy (m_ExplosionParticles.gameObject, m_ExplosionParticles.main.duration); Destroy (gameObject); } private float CalculateDamage(Vector3 targetPosition) { // Calculate the amount of damage a target should take based on it's position. Vector3 explosionToTarget = targetPosition - transform.position; float explosionDistance = explosionToTarget.magnitude; float relativeDistance = (m_ExplosionRadius - explosionDistance) / m_ExplosionRadius; float damage = relativeDistance * m_MaxDamage; damage = Mathf.Max(0f, damage); return damage; } }

試したこと

コメントにも書きましたがTakeDamageのm_CurrentHealth -= amount;を m_CurrentHealth += amount;でもう一つ定義したりifの後にelseをつけたりしましたが上手くいきませんでした。
よろしくお願いします。

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

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

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

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

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

fiveHundred

2021/12/24 02:28

提示された内容ではTakeDamage()を呼び出している箇所がどこにもないので、そこの具体的な内容を質問を編集して記載してください。 (というか、そもそもDamageという名前の関数で回復を行う、というのはすごく違和感があります)
guest

回答2

0

ベストアンサー

訂正
(1)自分で追加したスクリプト
HPItem.cs を以下に差し替えてください。

using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Complete { public class HPItem : MonoBehaviour { public LayerMask m_TankMask; // インスペクタで "Players" を指定してください。 private void OnTriggerEnter(Collider other) { Collider[] colliders = Physics.OverlapSphere(transform.position, 5f, m_TankMask); // Go through all the colliders... for (int i = 0; i < colliders.Length; i++) { Rigidbody targetRigidbody = colliders[i].GetComponent<Rigidbody>(); if (!targetRigidbody) continue; // TankHealth script の取得 TankHealth targetHealth = targetRigidbody.GetComponent<TankHealth>(); if (!targetHealth) continue; // 回復 targetHealth.Rehab(100); // 回復値MAX } Destroy(gameObject); } } }

投稿2021/12/25 02:22

monmoko

総合スコア202

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

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

0

fiveHundredさんの指摘にあるように TakeDamage()で回復させるのは混乱のもとになるので避けた方がよいでしょう。
ということで、以下のようにすると動作すると思います。

(1)自分で追加したスクリプト(回復オブジェクトにアタッチさせるスクリプト?)
Destroy(gameObject);行の直前に以下を追加

collision.GetComponent<TankHealth>().Rehab( m_StartingHealth );

(2)チュートリアルのスクリプト
以下のメソッドを追加

public void Rehab(float amount) { m_CurrentHealth += amount; if (m_CurrentHealth > m_StartingHealth ) { m_CurrentHealth = m_StartingHealth; //最大値(初期値)を超えないようにする } SetHealthUI(); //UIの更新 }

投稿2021/12/24 06:56

monmoko

総合スコア202

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

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

tr1996

2021/12/24 11:43

回答ありがとうございます。 スクリプトに追加したところ HPItem.cs(14,23): error CS1061: とエラーが出てしまいました。私の方に問題があると思うのですが、アドバイスお願いします。
tr1996

2021/12/24 12:48

collision.GetComponent<TankHealth>().Rehab( m_StartingHealth );にエラーが出ました。
monmoko

2021/12/25 02:22

すいません。 実際のチュートリアルを確認したら思ったより複雑なことをしていたようでした。 HPItem.cs の内容を回答欄に示しましたので、そちらを参照してください。
tr1996

2021/12/25 12:44

丁寧にありがとうございます。 参照させてもらったのですが、 HPItem.cs(30,30): error CS1061: 'TankHealth' does not contain a definition for 'Rehab' and no accessible extension method 'Rehab' accepting a first argument of type 'TankHealth' could be found とエラーが出たのですがアドバイスお願いします。 色々すみません・・・。 あとアイテムのオブジェクトにis Triggerにチェックを入れると再生画面でオブジェクトが消えてしまうのですが原因がわかりましたらお願いします。 何度もすみません。
monmoko

2021/12/25 23:15

たびたびすいません、チュートリアルのComplete 版で試していたので修正のコードに余計な記述がありました。 HPItem.cs の namespace Complete の行とその { } 行は不要です。削除してください。 これでerrorが治るか試してみてください。 また、オブジェクトが消えてしまう件ですが、私の方では再現できません。 Complete 版の方で試してみてください。 ただしこの場合、HPItem.csは、上記の削除をしないでそのままの使用となります。
tr1996

2021/12/26 04:54

解決しました。 丁寧な対応ありがとうございました。
tr1996

2021/12/28 04:25

すみません、時間差で申し訳ないのですが、 public LayerMask m_TankMask;のLayerMaskとはどんな時に使うのですか? 初歩的かもしれませんがお願いします。
monmoko

2021/12/28 10:26

マニュアルではレイヤーについて以下のように記述されています。 「レイヤー は、カメラ がシーンの一部のみを描画するために、また、ライト がシーンの一部のみを照らすためにもっとも頻繁に使用されます。しかし、レイキャスティングが選択的にコライダーを無視したり、 衝突 を発生させるためにも使用することができます。」 LayerMaskはこのレイヤーの取捨選択に使用します。 いくつかのオブジェクトを論理的なレイヤー(層)としてひとまとめにして扱うことで処理を簡略化させることができます。 よく使われるのはカメラに対してですが、このチュートリアルのようにコリジョンに対しても使えるようです。 工夫次第で他にも使えそうな気がします。
tr1996

2021/12/29 12:31

わかりやすくありがとうございました。 参考にします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問