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

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

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

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

Unity

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

Q&A

解決済

3回答

2466閲覧

他クラスの変数を書き換えたい。

jelatto

総合スコア11

C#

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

Unity

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

0グッド

0クリップ

投稿2019/05/01 02:13

編集2019/05/01 02:35

閲覧ありがとうございます。
C#を勉強しているものです。

現在GameController.csにある変数を、他クラスItem.csにて書き換えたいと思っています。
(挙動としては、Itemクラスでの値の変更をトリガーにしてGamecontrollerクラスのメソッドを動かしたいと考えております。unityのUpdate関数などを使わず実装したいです。)

他の質問者様の回答やネットで調べてみて色々試して以下の方法で試してみましたがうまくいきません。
C#に詳しい方いらっしゃいましたらご教授いただけないでしょうか。何卒よろしくお願いいたします。

1.GameController.csをItemでインスタンス化して値を代入する。→コンパイルエラーにはならないがnullになる。
2.GameController.csでバプリック変数を定義してItem.csから参照する。→コンパイルエラー。 error CS0120: An object reference is required to access non-static memberのエラーが出る。

C#

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.UI; 6 7public class GameController : MonoBehaviour { 8 9 public Text scoreLabel; 10 public GameObject winnerLabelObject; 11 12 public GameController instance = null; 13 14 private bool ObjDestroyed; 15 public bool _ObjDestroyed 16 { 17 get { 18 return ObjDestroyed; 19 } 20 21 set{ 22 ObjDestroyed = value; 23 } 24 25 } 26 27 private void Awake() 28 { 29 instance = this; 30 ObjDestroyed = false; 31 } 32 33 34 public void SetText() 35 { 36 if (ObjDestroyed != false) 37 { 38 int count = GameObject.FindGameObjectsWithTag ("Item").Length; 39 scoreLabel.text = count.ToString (); 40 41 if (count == 0) { 42 //オブジェクトをアクティブにする 43 winnerLabelObject.SetActive (true); 44 } 45 } 46 } 47} 48

C#

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5 6public class Item : MonoBehaviour { 7 8 private bool getObj; 9 10 private GameController _GameController = new GameController(); 11 12 13 //トリガーとの接触時に呼ばれるコールバック。 14 public void OnTriggerEnter(Collider hit) 15 { 16 //接触対象はPlayerタグですか? 17 if (hit.CompareTag ("Player")) 18 { 19 //このコンポーネントを持つGameObejctを破棄する。 20 Destroy (gameObject); 21 22 //1 23 _GameController._ObjDestroyed = true; 24 25 //2 26 GameController.instance._ObjDestroyed = true; 27 } 28 } 29} 30

主にこちらの記事を参考にしました。↓
別のクラスの変数の値を変更したい

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

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

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

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

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

y_waiwai

2019/05/01 02:23

どの変数をどういうふうに書き換えるんでしょうか
jelatto

2019/05/01 02:25

わかりにくく申し訳ありません。 GameControllerクラスのbool _ObjDestroyed変数をItemクラスで書き換えたいと思っております。
len_souko

2019/05/03 03:05

GameControllerクラスってインスタンスは一つだけしかないの?それとも複数できてしまうものなの?
jelatto

2019/05/03 22:22

ご質問ありがとうございます。GameControllerクラスのインスタンスは複数できてしまう構造になっています。Itemオブジェクトが複数あるので、そのオブジェクト分インスタンスができます。
len_souko

2019/05/04 06:06

ということは、GameControllerの_ObjDestroyedを参照するItemは一つに特定できる?それとも複数参照する?それとも逆にItem一つに対して複数のGameControllerを参照する? 必ず固定の対になるのなら、Itemの初期処理の際に参照するGameControllerのインスタンスを取得してやれば行けると思う YAmaGNZさんの1の方法のItemのStartメソッド内でやってるFindObjectOfTypeをFindObjectsOfTypeに変えてからどのGameControllerなのかを特定するキーの一致するインスタンスを拾うようにすれば行けると思う Unityは詳しくないので適当にググった「http://myoujing.wpblog.jp/2014/06/760/」をみただけやけど それとは別に、GameControllerって名前が適切かどうかって疑問はあるけど ゲームをコントロールするんじゃなくてItemをコントロールしてるんじゃぁ?って気が・・・多分今までに出てきてる回答はGameControllerって名前からゲーム全体を管理するものだという前提で考えてるものだと思うので
jelatto

2019/05/05 09:50

回答ありがとうございます。GameControllerの_ObjDestroyedを参照するItemは複数参照します!Item一つに対して複数のGameControllerは参照しません。GameControllerは1つだけ存在します。 名前は仰る通りだと思います。現在下記のUnityチュートリアルを一通り触ってみた上でもっと違う書き方ができないかを模索していたので、クラス名などはほとんど下記に忠実に作っておりそこまで気を遣えておりませんでした。しかしこちらで質問する際、そして開発を今後進める上でも不適切だと思いますので、適切な名前に変更していこうと思います。貴重なご意見ありがとうございます。 https://unity3d.com/jp/learn/tutorials/projects/hajiuni/creating-the-game-ui?playlist=45986
guest

回答3

0

ベストアンサー

1.のinstanceがnullになる理由

Awakeはマニュアルには「スクリプトのインスタンスがロードされたときに呼び出されます」とありますが、これはあくまでUnityEngine管理下である場合です。
(UnityEngine管理下でもActiveではないなどの理由でインスタンス化されても呼ばれない場合があります)
ただスクリプト内でnewした場合、UnityEngineは知らないのでStartやAwakeを呼ぶ機構が動作しないのではないかと思います。
ですので、Awakeでinstanceをセットしている部分が動作せずに初期値のnullのままとなっています。

2.のコンパイルエラーになる原因

instanceは
public GameController instance = null;
と定義してあり、staticで宣言してありません。
このため、インスタンス毎にことなる値を持つ通常の変数となります。
これをGameController.instanceとstatic変数として使用しようとしているのでコンパイルエラーとなります。

では、どうやってアクセスするかですが

1の方法の場合
GameController

C#

1public class GameController : MonoBehaviour { 2 3 public Text scoreLabel; 4 public GameObject winnerLabelObject; 5 6 public bool ObjDestroyed { get; set; } 7 8 private void Awake() 9 { 10 ObjDestroyed = false; 11 } 12 13 public void SetText() 14 { 15 if (ObjDestroyed != false) 16 { 17 int count = GameObject.FindGameObjectsWithTag ("Item").Length; 18 scoreLabel.text = count.ToString (); 19 20 if (count == 0) { 21 //オブジェクトをアクティブにする 22 winnerLabelObject.SetActive (true); 23 } 24 } 25 } 26}

Item

C#

1public class Item : MonoBehaviour { 2 3 private bool getObj; 4 private GameController _GameController; 5 6 void Start() 7 { 8 // GameController のインスタンスを見つける. 9 _GameController = FindObjectOfType<GameController>(); 10 } 11 12 //トリガーとの接触時に呼ばれるコールバック。 13 public void OnTriggerEnter(Collider hit) 14 { 15 //接触対象はPlayerタグですか? 16 if (hit.CompareTag("Player")) 17 { 18 //このコンポーネントを持つGameObejctを破棄する。 19 Destroy(gameObject); 20 21 //1 22 _GameController.ObjDestroyed = true; 23 } 24 } 25}

このような感じになるのではないかと思います。
(Unityはほぼ知らないので検索した内容で勘で書いていますので、動くかは分かりません)

2の方法の場合
GameController

C#

1public class GameController : MonoBehaviour { 2 3 public Text scoreLabel; 4 public GameObject winnerLabelObject; 5 6 public static bool ObjDestroyed { get; set; } 7 8 private void Awake() 9 { 10 ObjDestroyed = false; 11 } 12 13 public void SetText() 14 { 15 if (ObjDestroyed != false) 16 { 17 int count = GameObject.FindGameObjectsWithTag ("Item").Length; 18 scoreLabel.text = count.ToString (); 19 20 if (count == 0) { 21 //オブジェクトをアクティブにする 22 winnerLabelObject.SetActive (true); 23 } 24 } 25 } 26}

Item

C#

1public class Item : MonoBehaviour { 2 3 private bool getObj; 4 5 //トリガーとの接触時に呼ばれるコールバック。 6 public void OnTriggerEnter(Collider hit) 7 { 8 //接触対象はPlayerタグですか? 9 if (hit.CompareTag("Player")) 10 { 11 //このコンポーネントを持つGameObejctを破棄する。 12 Destroy(gameObject); 13 14 //2 15 GameController.ObjDestroyed = true; 16 } 17 } 18}

このようにstaticで宣言してやればいいのではないかと思います。

ほぼUnityを知らずに書いてますので、違う箇所があるなら訂正をお願いします。
(Unityの作法的には1の方法なのかな?とは思います。)

投稿2019/05/01 04:12

編集2019/05/01 04:13
YAmaGNZ

総合スコア10222

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

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

jelatto

2019/05/06 09:37

分かりやすく教えていただきありがとうございます。1と2の方法を試してみました。結果的にどちらもコードのエラーは出ないのですが、1の場合は値が変わらず、2の場合はUnityのゲームを起動するとStatic変数に値を代入する場面でUnityがクラッシュしてしまう問題に直面し、原因を探っています。 こちらの回答を元に引き続き原因を探りたいと思います。
YAmaGNZ

2019/05/06 11:08

GameControllerが複数できる構造とのことですので、1の方法の場合のFindObjectOfTypeで取得しているインスタンスと値が変化しているかチェックしているインスタンスが異なっているのだと思います。 ですので、他の方法で取得するべきだと思います。こういったあたりがUnityに詳しくない私ではアドバイス出来ない部分となります。
jelatto

2019/05/06 13:41

回答ありがとうございます。インスタンスの取得の仕方をもう少し勉強してみます。丁寧に教えていただき理解が深まりました。
guest

0

このように書き換えたら正常に動きました。
色々書き方を試しては書き換え、を繰り返していたため、余計なコードを書いてしまい自分で不具合が出ていると思っていたところと別のところでエラーが出てしまっていたようでした。
皆様の回答のおかげでより理解を深めることができました。
本当にありがとうございます!

C#

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.UI; 6 7public class GameController : MonoBehaviour { 8 9 public Text scoreLabel; 10 public GameObject winnerLabelObject; 11 12 public GameController instance; 13 private static int count = 0; 14 15 private bool ObjDestroyed; 16 public bool _ObjDestroyed 17 { 18 set { ObjDestroyed = value; 19 20 if (ObjDestroyed != false) 21 { 22 SetText(); 23 } 24 } 25 26 } 27 28 private void Awake() 29 { 30 instance = this; 31 ObjDestroyed = false; 32 33 count = GameObject.FindGameObjectsWithTag ("Item").Length; 34 scoreLabel.text = count.ToString (); 35 } 36 37 38 public void SetText() 39 { 40 if (ObjDestroyed != false) 41 { 42 count--; 43 scoreLabel.text = count.ToString (); 44 45 if (count == 0) { 46 //オブジェクトをアクティブにする 47 winnerLabelObject.SetActive (true); 48 } 49 } 50 ObjDestroyed = false; 51 } 52} 53 54

C#

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5 6public class Item : MonoBehaviour { 7 8 private bool getObj; 9 10 11 //トリガーとの接触時に呼ばれるコールバック。 12 public void OnTriggerEnter(Collider hit) 13 { 14 //接触対象はPlayerタグですか? 15 if (hit.CompareTag ("Player")) 16 { 17 GameController.instance._ObjDestroyed = true; 18 19 //このコンポーネントを持つGameObejctを破棄する。 20 Destroy (gameObject); 21 22 } 23 } 24}

投稿2019/05/11 03:44

jelatto

総合スコア11

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

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

0

private bool ObjDestroyed;
public bool ObjDestroyed;

にするというはなしかな?

投稿2019/05/01 02:28

y_waiwai

総合スコア87719

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

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

jelatto

2019/05/01 02:33

回答ありがとうございます。 いえ、private bool ObjDestroyedはpublic bool _ObjDestroyedに追跡させる用に定義しているので、こちらはprivateのままが良いと考えております。
y_waiwai

2019/05/01 02:37

あれ?なら、1番でうまくいくんじゃない?
YAmaGNZ

2019/05/01 02:53

1番でやるならGameControllerをnewしちゃダメなんじゃ? 実際に動いてるGameControllerと別インスタンスになってるんじゃないの?
k.matsuda

2019/05/01 02:55

解決になるかどうかわかりませんが、 ``` private bool ObjDestroyed = false; ``` で、初期化しておくってのはどうでしょうか?
y_waiwai

2019/05/01 03:02

> YAmaGNZ ああ、ほかのどこかにあるGameControllerをどーにかしたいってはなしなのか。 #ちと質問文だけじゃわからないけど そのどこかのインスタンスをどうにかして持ってきて、そいつの_ObjDestroyedに代入しなけりゃいけないというはなしなんですな
YAmaGNZ

2019/05/01 03:07

Unityだから何かのオブジェクトなりにアタッチされているスクリプトだと思う。 Unityは詳しくないんで取得方法は知らないけどGetComponentとかでインスタンスを取得してくるんじゃないのかな?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問