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

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

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

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

Unity

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

Q&A

解決済

3回答

1684閲覧

別クラスから呼び出した変数が同期されないようにするためにはどうすればいいですか[Unity]

sakas1231

総合スコア42

C#

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

Unity

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

0グッド

0クリップ

投稿2016/09/28 09:22

編集2016/09/28 11:35

口で説明するのが少し難しいのでお手数ですがまずはこのシンプルなコードを見てみてください

C#

1public class Input{ 2 public bool b = false; 3}

C#

1public class Output{ 2 bool b; 3 Input data; 4 void Start(){ 5 data = this.gameObject.getComponent<Input>(); 6 } 7 public void boFalse(){ 8 this.b = data.b; //この時点でthis.b = data.b = false 9 boTrue(); //data.bをtrueに帰るboTrueを呼び出す 10 print(this.b); //この時data.bがboTrueによってtrueとなったのでthis.bもtrueに変わり出力結果はtrue 11 } 12 13 public void boTrue(){ 14 data.b = true; //ここで参照しているdata.bをtrueに 15 } 16} 17

まずこの二つのクラスは同じオブジェクトにアタッチされているのでthis.gameObject.getComponentでdataにInputコンポーネントを代入します。
するとまるで同期したかように、data.bの値を変えるとthis.bの値も同時に変わります。

これを防ぐためにはどうすればいいのでしょうか
具体的には、仮にboTrueを呼び出すともちろんdata.bの値はtrueになりますがthis.bの値は変わらずに最初に参照したfalseのままでいる、ということです。

少し言葉足らずで申し訳ありませんが回答宜しくお願い致します。

以下編集で追加

申し訳ございません、上記のコードはかなり自分なりに簡略化したものでした

ただいまコンピュータを対戦相手とした一人用のオセロを作成していまして、その時に今自分が置いた場所とそれによって石がひっくり返った場所を記憶しておく必要があります。
そこでOzero.cs内のbool[8,8]型変数putSpaceとturnOrNotを利用します。
以下のコードで言うところのozero.putSpaceでおいたところをtrueに、turnOrNotでひっくり返ったところをtrueとするbool[8,8]型がそれに当たります。

ここでやりたいことは、コンピュータ内で2手先までの全ての可能性を読むのですが(木をイメージしてください)、1手目を読んだ時に置いたところとひっくり返ったところを記憶しておきながら2手目で再び同じ動作をしたいです。(evalあたりは今回は関係ないので省略いたしました)
その際に、putSpaceとturnOrNotを二回呼び出さなければいけません。
以下に実際にハマったコードを記載します

c#

1void Start () { 2 ozero = this.gameObject.GetComponent<Ozero> (); 3 undo = this.gameObject.GetComponent<Undo> (); 4 } 5 6 public void minMax(){ //最初のcpuの思考を考える 7 for (int i = 0; i < 8; i++) { 8 for (int j = 0; j < 8; j++) { 9 if (ozero.canPutOrNot(i,j,false,true)) { //cpuがそこに石を置ける時 10 put = ozero.putSpace; //置いたところとturnしたところを記憶 11 turn = ozero.turnOrNot; 12 x = i; y = j; //cpuが最初に置いた時のxyを記憶 13 ozero.checkTurn *= -1; //ターンチェンジしてこれからplayerに 14 //これからplayerのターン(木の真ん中) 15 minMax2 (); //ここで高さ1の要素一つ分を見終える(*64) 16 evalMax (); 17 minScore = System.Int32.MaxValue; //ここで一旦最小値探索リセット 18 undo.back(put,turn); //undoして振り出しに 19 20 } 21 } 22 } 23 } 24 public void minMax2(){ //playerの思考を考える 25 for (int i = 0; i < 8; i++) { 26 for (int j = 0; j < 8; j++) { 27 if (ozero.canPutOrNot (i, j, false, true)) { //playerがそこに石を置ける時 28 ozero.checkTurn *= -1; //ターンチェンジしてこれからcpuに 29 //これからcpuのターン(木の葉の時)評価してundo 30 evalScore (); 31 evalMin (x, y); 32 undo.back (ozero.putSpace, ozero.turnOrNot); //このパターンの探索終了したら一つ戻す(木の真ん中のplayer) 33 34 } 35 } 36 } 37 }

この時、minMax2で最後にozero.backの引数として先ほどの二つを渡しているのですが、この瞬間にozero.putSpaceとozero.turnOrNotが更新されてしまい、最初にputとturnに渡した値が更新されてしまうようです。
これの改善方法はありますでしょうか
宜しくお願い致します

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

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

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

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

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

guest

回答3

0

ベストアンサー

こんにちは。

これは質問のために簡単化したコードということはないでしょうか?
もし、bがbool型ではなくクラス型であれば発生します。
クラスは参照型なので、実装的にはクラス・オブジェクトへのポインタです。つまり、this.b = data.b;でthis.bとdata.bが同じオブジェクトへのポインタを保持することになります。

bがbool型で発生しているのでしたら、ごめんなさい。bool型は値型なので原因は上記ではないです。

投稿2016/09/28 10:01

Chironian

総合スコア23272

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

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

sakas1231

2016/09/28 11:20

編集で記しておきましたが、bはbool[8,8]型です 原因は別のところなのでしょうか
sakas1231

2016/09/28 15:08

なるほど、参照型でしたか。 無事bool[8,8]型を二重for文を利用してboolに直して解決できました。 とても参考になるリンクありがとうございます!
guest

0

この内容だとboFalse()を二回呼んだら、その後何をしても、this.bもdata.bも常時trueを返すようになってしまいますが、その辺りは想定通りでしょうか?

投稿2016/09/28 09:49

ishi9

総合スコア1294

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

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

sakas1231

2016/09/28 11:32

詳しく考えずに作成してしまったのでこのようん変なコードになってしまい申し訳ありません。 編集で詳しく追加しましたのでそちらを確認していただけると幸いです。
guest

0

これってコードすべてですか?
MonoBehaviourを継承していなかったり、getComponent(正確には GetComponent)になっていたり、このままだと動かないコードなので。

もし端折っている部分があるんだとしたら、そちらに問題があるかもしれないので、現状のコードを載せてるといいかもしれません。

少なくとも今のコードでは this.b に影響はないように見えます。

投稿2016/09/28 09:37

編集2016/09/28 09:38
edo_m18

総合スコア2283

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

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

sakas1231

2016/09/28 11:29

かなり端折っていましたので、編集で追加しておきました。そちらを確認していただけるとありがたいです。 この場合どうなるのでしょうか
edo_m18

2016/09/28 13:33

なるほど。すでに下で回答されていますが、まさに「参照型」によるものですね。 なので内容をコピーして、配列自体を参照しないように改修すれば問題は解消できると思います。 あと、参照型と値型についてはもう少し深く学んでおいたほうがいいと思います。 慣れないとそのあたりでハマる・バグが出ることが多いので。
sakas1231

2016/09/28 15:07

ありがとうございました! 参照型とデータ型はもともと知識としては知っていたのですがここでその考えが出てきませんでした。 知識を蓄えてもそれを利用しないと無駄ということに気づかされました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問