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

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

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

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

Unity

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

Q&A

解決済

1回答

4693閲覧

[Unity] 他のGameObject中の変数の変更を検知するスマートな方法が知りたい

ai2playgame

総合スコア15

C#

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

Unity

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

0グッド

0クリップ

投稿2020/04/24 03:35

Unityにおいて、あるGameObjectが更新された時だけUIの描画変更メソッドを呼び出すといった、同じシーンにあるGameObjectが持つコンポーネントの変数の変更を検知する、スマートな方法が知りたいです。
私はこういった時にはUpdate() を使って、以下のような形で実装することが多いです。

c#

1public class Player : MonoBehaviour 2{ 3 public int HP { get; private set; } = 100; 4 5 private void Update() 6 { 7 // なにかしらの処理 8 9 // HPの書き換え 10 HP -= 10; 11 } 12} 13 14public class PlayerHPWidget : MonoBehaviour 15{ 16 // インスペクタで設定 17 public Player player = null; 18 private void Update() 19 { 20 UpdateWidget(); 21 } 22 private void UpdateWidget() 23 { 24 // player.HPの値に応じて処理を変える 25 if (player.HP == 100) { Debug.Log("満タン"); } 26 else if (player.HP >= 50) { Debug.Log("まだまだ"); } 27 else if (player.HP >= 20) { Debug.Log("そろそろ回復"); } 28 else if (player.HP > 0) { Debug.Log("危険!"); } 29 else { Debug.Log("死亡"); } 30 } 31} 32

この実装では UpdateWidget() がさほど大きなコストがかからないため、問題とならないと思われます。しかし将来的に UpdateWidget() が肥大化した時、 MonoBehaviorの Update() の中で毎回呼び出すのは、明らかに負荷となると考えています。

この問題の解決策として、Player側に PlayerHPWidget の参照をもたせておき、HPを書き換える度にそこから UpdateWidget() を呼び出すというのを考えました。

C#

1public class Player : MonoBehaviour 2{ 3 public int HP { get; private set; } = 100; 4 public PlayerHPWidget widget = null; 5 private void Update() 6 { 7 // なにかしらの処理 8 9 // HPの書き換え 10 HP -= 10; 11 widget.UpdateWidget(); 12 } 13}

しかしこれでは、PlayerとPlayerHPWidgetが相互に依存しており良い実装とは言えないと思います。

なにか良い実装はあるでしょうか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

色々な方法が考えられますが、現状の実装に対してある程度手軽に、かつ負荷軽減の意味で使えるのはeventかなと思います。

以下のような実装はいかがでしょうか?

public class Player : MonoBehaviour { public event System.Action<int> OnUpdateHP; public int HP { get; private set; } = 100; private void Update() { // なにかしらの処理 // HPの書き換え HP -= 10; if (OnUpdateHP != null) OnUpdateHP.Invoke(HP); // C#6以降(だったかな?)なら簡単に以下のように書けます //OnUpdateHP?.Invoke(HP); } }

利用する側はこんな感じです。

public class PlayerHPWidget : MonoBehaviour { // インスペクタで設定 public Player player = null; private void Awake() { player.OnUpdateHP += UpdateWidget; } private void UpdateWidget(int hp) { // player.HPの値に応じて処理を変える if (hp == 100) { Debug.Log("満タン"); } else if (hp >= 50) { Debug.Log("まだまだ"); } else if (hp >= 20) { Debug.Log("そろそろ回復"); } else if (hp > 0) { Debug.Log("危険!"); } else { Debug.Log("死亡"); } } }

これであれば、Player側はその他、どんなクラスが存在しているか気にする必要はなく、自分の処理に集中することができます。

投稿2020/04/24 03:42

編集2020/04/24 03:43
edo_m18

総合スコア2283

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問