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

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

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

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

Unity

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

Q&A

解決済

2回答

394閲覧

Unity 2つのListの中身が共有してしまう

JectABC

総合スコア34

C#

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

Unity

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

0グッド

0クリップ

投稿2017/12/26 03:16

編集2017/12/26 05:09

###前提・実現したいこと
以下のコードでchartest型のListの内容を変化させた時、すべてのchartest型Listに適用されてしまいます。同じものを参照しているからでしょうか?
共有させない方法がありますか?
具体的に言うとcccとcceeのmoveが別の結果になる方法がありますか?

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

エラーメッセージはありません

###該当のソースコード

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.UI; 5using UnityEngine.EventSystems; 6 7public class GameManager : MonoBehaviour { 8 9 public List<chartest> EEEEEEE = new List<chartest>(); 10 11 public Decktest ddd; 12 public chartest ccc; 13 public chartest ccee; 14 15 void Start () { 16 ddd = new Decktest(); 17 ddd.AllAdd(); 18 ddd.firstDekkiInit(); 19 //EEEEEEE = new List<chartest>(ddd.mydekki); 20 //データ追加 21 EEEEEEE.Add(ddd.chars[0]); 22 EEEEEEE.Add(ddd.chars[1]); 23 EEEEEEE.Add(ddd.chars[2]); 24   //テスト1 25 ccc = ddd.mydekki[1]; 26 ccee = EEEEEEE[1]; 27 28 ccc.Move_skills(ddd.chars[2].move); 29 30 Debug.Log("start test1"); 31 Debug.Log("ccc"); 32 for(int i = 0;i<8;i++){ 33 Debug.Log(ccc.move[i]); 34 } 35 Debug.Log(ccee"); 36 for(int i = 0;i<8;i++){ 37 Debug.Log(ccee.move[i]); 38 } 39 //テスト2 40 ccc2 = ddd.mydekki[0]; 41 ccee2 = EEEEEEE[0]; 42 43 ccc2.InitStatus(ddd.chars[2]); 44 Debug.Log("start test2"); 45 Debug.Log("ccc"); 46 for(int i = 0;i<8;i++){ 47 Debug.Log(ccc2.move[i]); 48 } 49 Debug.Log("ccee"); 50 for(int i =0 ;i<8;i++){ 51 Debug.Log(ccee2.move[i]); 52 } 53 54 } 55} 56
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Decktest : MonoBehaviour { public List<chartest> chars = new List<chartest>(); public List<chartest> mylist = new List<chartest>(); public List<chartest> mydekki = new List<chartest>(); public void firstDekkiInit(){ mylist.Add(chars[0]); mylist.Add(chars[1]); mylist.Add(chars[2]); foreach(var v in mylist){ mydekki.Add(v); } } public void AllAdd(){ chars.Add (new chartest (1,0,0,0,0,0,0,0)); chars.Add (new chartest (0,8,0,8,0,8,0,8)); chars.Add (new chartest (1,1,1,1,1,1,1,1)); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class chartest :MonoBehaviour{ public int[] move = new int[8]; public chartest(int N,int NE,int E,int SE,int S,int SW,int W,int NW){ move[0] = N; move[1] = NE; move[2] = E; move[3] = SE; move[4] = S; move[5] = SW; move[6] = W; move[7] = NW; } public void InitStatus(chartest t){ this.move = t.move; } public void Move_skills(int[] m){ for(int y = 0;y<8;y++){ this.move[y] = this.move[y] + m[y]; if(move[y]>8) move[y] = 8; } } }

###試したこと
参照が同じなのが原因かと思い、値渡しでEEEEEEEを作成してみましたが同じ結果でしたGamemanagerクラスでコメントアウトしているコードがそれにあたります。
また、質問用コードでは再現できませんでしたが、実際の環境ではchartestクラスのInitStatus()でmoveを変更させた時は別の結果になりました。
Move_Skillsによるmoveの変更方法ではcccとcceeの内容が共有されてしまいます。

###補足情報(言語/FW/ツール等のバージョンなど)
unity 2017.2.0f3 Personal
C#

Start()結果
start test1
ccc
1
8
1
8
1
8
1
8
ccee
1
8
1
8
1
8
1
8
start test2
ccc
1
1
1
1
1
1
1
1
ccee
1
1
1
1
1
1
1
1

 不足していることや解決のために足りない情報があればお伝えします。
宜しくお願いします。

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

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

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

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

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

guest

回答2

0

ku__ra__geさんの回答へのコメントに対する回答です。この内容で解決した場合は、ku__ra__geさんをベストアンサーにしてください。

値だけ渡せる、もしくはmylist.Add(new chartist[0]);このようなことはできませんか?

以下のようにするのはどうでしょうか?

・Decktestクラス

C#

1 mylist.Add(new chartest(chars[0])); 2 mylist.Add(new chartest(chars[1])); 3 mylist.Add(new chartest(chars[2])); 4 5 foreach (var v in mylist) 6 { 7 mydekki.Add(new chartest(v)); 8 }

・chartestクラス

C#

1 // chartestクラスに以下のコンストラクタを追加 2 public chartest(chartest original) 3 { 4 // 配列のコピーを行う 5 Array.Copy(original.move, this.move, this.move.Length); 6 }

質問とは関係ないですが、2点ほど。

  • newで生成するクラス(Decktestとchartest)にMonoBehaviourを継承しないでください。
    MonoBehaviourはゲームオブジェクトにアタッチして使うクラスなので、newされることを前提としていません。
    warningも出ていると思いますので、修正してください。
  • EEEEEEEやcccといった名前は非常に分かりづらいです。
    他の人が見ても分かりやすい名前の方がよいです。
    自分しか編集しないようなものでも、後から見直すと「これってどんな変数だっけ?」ってなってしまいます。

投稿2017/12/27 03:24

fiveHundred

総合スコア9803

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

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

JectABC

2017/12/27 12:27

ありがとうございます。コピーの件は解決しました! アタッチするクラスをnewしてはいけないというのは自分の中の根底を覆されたような感覚です。今まで当たり前のようにしていました。記述をしていませんでしたがこのchartestクラスはオブジェクトにアタッチするものですので、MonoBehaviourの継承は避けられません。newを使うのをやめたほうがいいということですね。こちらについてはまた改めて質問させていだだきます。 変数の名前は質問のためにつけたものです。逆にわかりづらくなったことお詫び申し上げます。
guest

0

ベストアンサー

chartest型のListの内容を変化させた時、すべてのchartest型Listに適用されてしまいます。同じものを参照しているからでしょうか?

はい。
コード1で、変数ccccceeが指すものは同じオブジェクトです。

「テスト1」に関して言えば、
cccddd.mydekki[1]です。
cceeEEEEEEE[1]であり、EEEEEEE[1]ddd.chars[1]です。
リスト2で定義されているDecktestクラスのfirstDekkiInit()を見ると、mydekkichars[0]chars[2]が代入される動作になっています。
よって、ddd.mydekki[1]ddd.chars[1]は同じオブジェクトを指しています。

共有させない方法がありますか?
具体的に言うとcccとcceeのmoveが別の結果になる方法がありますか?

リスト2 DecktestクラスのfirstDekkiInit()で、既に存在するインスタンスを代入しないようにしてください。

C#

1public void firstDekkiInit(){ 2 mylist.Add(new chartest (1,0,0,0,0,0,0,0)); 3 mylist.Add(new chartest (0,8,0,8,0,8,0,8)); 4 mylist.Add(new chartest (1,1,1,1,1,1,1,1)); 5 6 mydekki.Add(new chartest (1,0,0,0,0,0,0,0)); 7 mydekki.Add(new chartest (0,8,0,8,0,8,0,8)); 8 mydekki.Add(new chartest (1,1,1,1,1,1,1,1)); 9}

投稿2017/12/26 05:21

ku__ra__ge

総合スコア4524

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

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

JectABC

2017/12/26 08:55

ありがとうございます。違う結果になりました! しかしこの方法ではデータが多くなった時に対応できません。値だけ渡せる、もしくは mylist.Add(new chartist[0]);このようなことはできませんか? 上のようなコードはもちろん使えませんが...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問