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

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

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

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

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

Q&A

解決済

1回答

766閲覧

クラスの中のクラスが参照渡しになってしまいます。

kenji007

総合スコア22

C#

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

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

0グッド

0クリップ

投稿2023/01/23 08:31

編集2023/01/23 12:30

C#

1 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using System.Linq; 6 7public class Test : MonoBehaviour 8{ 9 [System.Serializable] 10 public class Party 11 { 12 public List<Char> Chars; 13 14 public object Clone() 15 { 16 Party tmpParty; 17 tmpParty = (Party)this.MemberwiseClone(); 18 19 tmpParty.Chars = tmpParty.Chars.ToList(); 20 21 return tmpParty; 22 } 23 } 24 25 26 [System.Serializable] 27 public class Char 28 { 29 public int Char_ID; 30 public string Char_Name; 31 public List<Item> Char_Items = new List<Item>(); 32 } 33 34 [System.Serializable] 35 public class Item 36 { 37 public string Name; 38 public int Count; 39 } 40 41 public List<Party> SaveData = new List<Party>(); 42 43 [SerializeField] 44 public Party SaveData_Playing; 45 46 void Start() 47 { 48 Item Item1 = new Item(); 49 Item1.Name = "回復剤"; 50 Item1.Count = 1; 51 52 Item Item2 = new Item(); 53 Item2.Name = "武器"; 54 Item2.Count = 2; 55 56 Char Man=new Char(); 57 Man.Char_ID = 1; 58 Man.Char_Name = "オトコ"; 59 Man.Char_Items.Add(Item1); 60 Man.Char_Items.Add(Item2); 61 62 Item Item3 = new Item(); 63 Item1.Name = "魔法剤"; 64 Item1.Count = 3; 65 66 Item Item4 = new Item(); 67 Item2.Name = "なんか"; 68 Item2.Count = 4; 69 Char WoMan = new Char(); 70 WoMan .Char_ID = 2; 71 WoMan .Char_Name = "オンナ"; 72 WoMan .Char_Items.Add(Item3); 73 WoMan .Char_Items.Add(Item4); 74 75 SaveData_Playing.Chars.Add(Man); 76 SaveData_Playing.Chars.Add(WoMan); 77 78 SaveData.Add(new Party()); 79 SaveData[0]=(Party)SaveData_Playing.Clone(); 80 81 } 82}

上記のようなスクリプトを作りました。
ざっくりですが、ゲームを遊んでいてプレイ状況をセーブしたときの挙動想定しています。

79行目の
SaveData[0]=(Party)SaveData_Playing.Clone();
でセーブスロットにセーブデータを保存したつもりです。

ただ、実際に動かしてみると
SaveData_PlayingとSaveDataが一部同期してしまっており困っております。
例えば、Manの回復剤を2にすると、セーブをしたデータの
SaveData[0]
こちらまで一緒に2に切り替わってしまいます。
ネットで調べた限りだと値渡しのコピー(?)や、DeepCopyをする、と書いてあるのですが、どこをどうしたら良いかわからず、お知恵を貸していただけますと幸いです

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2023/01/23 09:04 編集

コーの表示が崩れています。直してください。 Unity のタグをつけてください。 > 値渡しのコピーなどをすれば良いと思うのですが 意味不明です。具体的にコードのどこをどうしたいのか書いてください。
y_waiwai

2023/01/23 09:10

このままではコードが読みづらいので、質問を編集し、</>(コードの挿入)ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
退会済みユーザー

退会済みユーザー

2023/01/23 09:19

> 出てくる’’’の枠の中に・・・ 毎回間違えてますが ’’’ ではなくて ``` です。(バッククオート 3 つ) 
ozwk

2023/01/23 09:29

おっしゃりたい意味はわかるので些事なのですが C#では「参照渡し」は全く別の事象を指しています。
YAmaGNZ

2023/01/23 12:10

WoManとManを間違えているところがありますが、元ソースでもそうなっているのですか?
kenji007

2023/01/23 12:30

失礼しました。 コード挿入とUnityタグについて追加させていただきました。 また、質問文を補足させていただきました。 また、「WoManとManを間違えているところ」コチラも修正させていただきました。
退会済みユーザー

退会済みユーザー

2023/01/23 12:47

Microsoft のドキュメントによると、 "MemberwiseClone メソッドは、新しいオブジェクトを作成し、現在のオブジェクトの非静的フィールドをその新しいオブジェクトにコピーすることによって、簡易コピーを作成します。フィールドが値型の場合、そのフィールドはビット単位でコピーされます。フィールドが参照型の場合、参照はコピーされますが、参照先オブジェクトはコピーされないため、元のオブジェクトとその複製は同じオブジェクトを参照します。" ・・・ということです。 上の一番最後のところが原因では?
guest

回答1

0

ベストアンサー

tmpParty = (Party)this.MemberwiseClone();

Microsoft のドキュメントによると、

"MemberwiseClone メソッドは、新しいオブジェクトを作成し、現在のオブジェクトの非静的フィールドをその新しいオブジェクトにコピーすることによって、簡易コピーを作成します。フィールドが値型の場合、そのフィールドはビット単位でコピーされます。フィールドが参照型の場合、参照はコピーされますが、参照先オブジェクトはコピーされないため、元のオブジェクトとその複製は同じオブジェクトを参照します。"

・・・ということです。 上の文の一番最後のところ「参照先オブジェクトはコピーされないため、元のオブジェクトとその複製は同じオブジェクトを参照します」が原因では?

Party クラスの Clone メソッドを手直しして、参照先のクラス定義から新たに別インスタンスを作って上で言う「参照先オブジェクト」の中身をコピーするようにしてはいかが?

以下のような感じ。

C#

1using System; 2using System.Collections.Generic; 3using System.Globalization; 4 5namespace ConsoleApp5 6{ 7 internal class Program 8 { 9 static void Main(string[] args) 10 { 11 Party SaveData_Playing = new Party(); 12 SaveData_Playing.Chars = new List<Char>(); 13 14 Item Item1 = new Item(); 15 Item1.Name = "回復剤"; 16 Item1.Count = 1; 17 18 Item Item2 = new Item(); 19 Item2.Name = "武器"; 20 Item2.Count = 2; 21 22 Char Man = new Char(); 23 Man.Char_ID = 1; 24 Man.Char_Name = "オトコ"; 25 Man.Char_Items.Add(Item1); 26 Man.Char_Items.Add(Item2); 27 28 Item Item3 = new Item(); 29 Item3.Name = "魔法剤"; 30 Item3.Count = 3; 31 32 Item Item4 = new Item(); 33 Item4.Name = "なんか"; 34 Item4.Count = 4; 35 36 Char WoMan = new Char(); 37 WoMan.Char_ID = 2; 38 WoMan.Char_Name = "オンナ"; 39 WoMan.Char_Items.Add(Item3); 40 WoMan.Char_Items.Add(Item4); 41 42 SaveData_Playing.Chars.Add(Man); 43 SaveData_Playing.Chars.Add(WoMan); 44 45 Party saveData = SaveData_Playing.Clone(); 46 47 Console.WriteLine($"Name; {SaveData_Playing.Chars[0].Char_Items[0].Name}, " + 48 $"Count: {SaveData_Playing.Chars[0].Char_Items[0].Count}"); 49 50 SaveData_Playing.Chars[0].Char_Items[0].Count = 2; 51 Console.WriteLine($"Name; {SaveData_Playing.Chars[0].Char_Items[0].Name}, " + 52 $"Count: {SaveData_Playing.Chars[0].Char_Items[0].Count}"); 53 Console.WriteLine($"Name: {saveData.Chars[0].Char_Items[0].Name}, " + 54 $"Count: {saveData.Chars[0].Char_Items[0].Count}"); 55 } 56 } 57 58 public class Party 59 { 60 public List<Char> Chars; 61 62 public Party Clone() 63 { 64 Party tempParty = new Party(); 65 tempParty.Chars = new List<Char>(); 66 foreach (Char c in this.Chars) 67 { 68 Char tempChar = new Char 69 { 70 Char_ID = c.Char_ID, 71 Char_Name = c.Char_Name, 72 Char_Items = new List<Item>() 73 }; 74 foreach (Item i in c.Char_Items) 75 { 76 Item tempItem = new Item 77 { 78 Name = i.Name, 79 Count = i.Count 80 }; 81 tempChar.Char_Items.Add(tempItem); 82 } 83 tempParty.Chars.Add(tempChar); 84 85 } 86 87 return tempParty; 88 } 89 } 90 91 public class Char 92 { 93 public int Char_ID; 94 public string Char_Name; 95 public List<Item> Char_Items = new List<Item>(); 96 } 97 98 public class Item 99 { 100 public string Name; 101 public int Count; 102 } 103}

結果は:

Name; 回復剤, Count: 1
Name; 回復剤, Count: 2
Name: 回復剤, Count: 1

投稿2023/01/23 14:16

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

kenji007

2023/01/23 14:40

ありがとうございます! 頂いた改修内容で試してみたいと思います。 たすかります!!
退会済みユーザー

退会済みユーザー

2023/01/23 23:11

途中経過のセーブであれば、JSON 文字列にシリアル化してファイルに保存するようにしてはいかがですか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.45%

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

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

質問する

関連した質問