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

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

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

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

Unity

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

Q&A

解決済

2回答

984閲覧

同オブジェクトの他スクリプト内の変数をうまく取得できているかわからない。

wagato

総合スコア1

C#

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

Unity

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

0グッド

0クリップ

投稿2023/08/20 08:44

実現したいこと

同じオブジェクトの他スクリプトの変数を取得したい。

前提

C#、Unity歴2ヶ月未満。初心者。
Unityを使い、C#を使用しています。同じオブジェクトの他スクリプトの変数を取得したいのですがうまくいきません。

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

”Beam"というタグが衝突するごとにHpが-1されていくメソッドを使用し、Hpを更新しています。他スクリプトからHp変数を取得しているのですがOncollisionEnter()メソッド内で更新している値を返さないと意味がないということでしょうか?自分は変数の初期値を取得しているということなのでしょうか?

エラーメッセージは特にないです。

該当のソースコード

C#

1コード 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.UI; 6 7public class PlayerHitpoint : MonoBehaviour 8{ 9 10 int maxHp = 10; 11 public int Hp; 12 13 public Slider slider; 14 // Start is called before the first frame update 15 void Start() 16 { 17 slider.value = 1; 18 Hp = maxHp; 19 } 20 21 // Update is called once per frame 22 void Update() 23 { 24 25 } 26 27 void OnCollisionEnter(Collision collision) 28 { 29 if(collision.gameObject.tag == "Beam") 30 { 31 Hp = Hp - 1; 32 slider.value = (float)Hp / (float)maxHp; 33 34 } 35 } 36} 37 38 39C# 40ソースコード 41using System.Collections; 42using System.Collections.Generic; 43using UnityEngine; 44using UnityEngine.UI; 45 46public class GameOver : MonoBehaviour 47{ 48 public Text gameOverMessage; 49 PlayerHitpoint HitPoint; 50 float PlayerHp; 51 52 53 // Start is called before the first frame update 54 void Start() 55 { 56 PlayerHitpoint HitPoint = GetComponent<PlayerHitpoint>(); 57 float PlayerHp = HitPoint.Hp; 58 } 59 60 // Update is called once per frame 61 void Update() 62 { 63 if(PlayerHp < -0.1) 64 { 65 gameOverMessage.text = "Game Over"; 66 Time.timeScale = 0f; 67 } 68 } 69 70 71} 72 73 74### 試したこと 75PlayerHitpointクラスのOncollisionEnter()メソッド内でreturn HpとしましたがVoidで宣言しているためできずです。更新している値をreturnで返すという考え方は正解なのでしょうか。 76

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

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

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

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

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

guest

回答2

0

ベストアンサー

やりたいこととしては、PlayerのHPが0になったら自動的にゲームオーバーになるようにしたいという感じでしょうかね?

自分は変数の初期値を取得しているということなのでしょうか?

現在の書き方だとそうですね。
float PlayerHpはStartの中で呼ばれて以降、一度も更新されません。
Updateの中でプレイヤーのリアルタイムのHPを見たければ、HitPoint.Hpを見る必要があります。

余談1

PlayerHpがオブジェクトをチェックしてダメージを計算する仕組みはおすすめしません。

csharp

1 void OnCollisionEnter(Collision collision) 2 { 3 if(collision.gameObject.tag == "Beam") 4 {

なぜなら障害物やオブジェクトを増やすたびにプレイヤーのif文を増やして処理を書かなかればいけないからです。
PlayerHpにvoid Damge(int damageAmount)といった、基本的なHP増減メソッドを定義し、ダメージを与えるオブジェクト側(今回だとBeam側)がPlayerHpを呼び出すといいです。
つまりこうです。

Beam.cs

csharp

1 private void OnTriggerEnter(Collider other) 2 { 3 PlayerHp playerHp = other.GetComponent<PlayerHp>(); 4 if (playerHp) 5 { 6 playerHp.Damage(1); 7 } 8 }

最初の書き方では、PlayerHpはダメージを与えるオブジェクトを全て知らなければならないですが、
こちらの書き方は ダメージを与えるオブジェクトがPlayerHpだけを知っていればいい ので、オブジェクトが増えたときにコードがすっきり分かりやすくなります。

余談2

特定の値になったときに処理を呼び出すようにしたいのであれば、デリゲートを使うといい感じです。
UnityにはUnityEventという仕組みがあるので、今回のケースだと以下のように書けます。
(コードをアタッチしたあとに、インスペクターでonDeathにGameOver.OnGameOverを登録する必要があります)

PlayerHp.cs

csharp

1using UnityEngine; 2using UnityEngine.Events; 3 4public class PlayerHp : MonoBehaviour 5{ 6 private int maxHp = 10; 7 public int Hp; 8 public UnityEvent onDeath; 9 10 void Start() 11 { 12 Hp = maxHp; 13 } 14 15 public void Damage(int damageAmount) 16 { 17 Hp -= damageAmount; 18 19 if (Hp <= 0) // 死んだときに 20 { 21 Hp = 0; 22 onDeath.Invoke(); // インスペクターで登録した他クラスの死亡時に呼び出したいメソッドを呼ぶ 23 } 24 } 25}

GameOver.cs

csharp

1using UnityEngine; 2 3public class GameOver : MonoBehaviour 4{ 5 public void OnGameOvver() 6 { 7 Debug.Log("Game Over!"); 8 } 9}

余談1、2のコードを合わせると、

  1. OnTriggerEnterでBeamがPlayerHpにダメージを与える
  2. PlayerHpがHpを計算する
  3. 計算した結果、Hp =< 0だったらGameOverを呼び出す

という処理の流れになり、Updateで常時監視する必要がなくなり、Hp =< 0の瞬間だけゲームオーバーが呼び出されるようになります。

投稿2023/08/20 11:14

編集2023/08/20 11:52
UnchFullburst

総合スコア669

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

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

0

C#

1 void Start() 2 { 3 PlayerHitpoint HitPoint = GetComponent<PlayerHitpoint>(); 4 float PlayerHp = HitPoint.Hp; 5 } 6

このfloat PlayerHp = HitPoint.Hp;は変数を宣言して代入しています。
変数の宣言や代入に関しての文法、変数のスコープについて学習されることをお勧めします。

投稿2023/08/20 09:56

YAmaGNZ

総合スコア10548

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

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

wagato

2023/08/20 10:04

すみません、申し訳ないのですがその文だけですと具体的な解決方法がわかりません。
YAmaGNZ

2023/08/20 11:13

まず float PlayerHp = HitPoint.Hp; これが何をしているのか理解されていますか?
wagato

2023/08/20 14:13

PlayerHitpointクラスのHp変数をGameOverクラスのPlayerHp変数に代入しています!!
YAmaGNZ

2023/08/20 22:02

違います。 float型のPlayerHpという名前の変数をStartメソッド内で定義し、その定義した変数にHitPoint.Hpを代入しています。 新しく宣言しているのでGameOverクラスのローカルで宣言しているfloat PlayerHp;とは別のものとなります。 こういった変数の宣言や代入、変数のスコープに関してはプログラムを作成するうえで基本的なこととなりますので「変数の宣言や代入に関しての文法、変数のスコープについて学習されることをお勧めします」と回答しました。
wagato

2023/08/21 12:33

なるほど!!ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問