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

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

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

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

Unity

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

Q&A

解決済

1回答

2313閲覧

Prefabがデバッグ実行時に更新されてしまう

eckolo

総合スコア27

C#

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

Unity

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

0グッド

0クリップ

投稿2016/11/03 14:46

###前提
アクション系のゲームを作成しています。
Unityはほぼ初心者です。

下記のようなクラス構成において、ClassAをアタッチしたPrefabをあるゲームオブジェクトに記憶させています。

C#

1public class ClassA : MonoBehaviour 2{ 3 public ClassC instanceC0 = new ClassC(); 4 5 public class ClassB 6 { 7 public string name = ""; 8 public ClassC instanceC1 = new ClassC(); 9 } 10 public ClassB instanceB 11 { 12 get 13 { 14 return new ClassB 15 { 16 name = gameObject.name, 17 instanceC1 = instanceC0, 18 }; 19 } 20 set 21 { 22 value = value ?? new ClassB(); 23 instanceC0 = value.instanceC1; 24 } 25 } 26} 27public class ClassC : MonoBehaviour 28{ 29 //中略 30}

###発生している問題
デバッグ実行中にClassAのアタッチされたオブジェクト(Object0)のinstanceBをClassAのアタッチされた別のオブジェクト(Object1)のinstanceBへ代入します。
ここでObject1のinstanceC0を更新すると、Prefabとして保存されているObject0のメンバinstanceC0まで更新されてしまいます。

C#

1ClassA instanceA0; 2ClassA instanceA1; 3//中略 4instanceA0.instanceB = instanceA1.instanceB; 5instanceA0.instanceC = new ClassC();

上記のコードの場合は、最終行実行時にPrefabにアタッチされたinstanceA1のメンバーinstanceC0が更新されます。
さらに一度デバッグ実行を終了しても更新されたデータはそのままです。
Prefabはゲーム中の動作に影響されずデータを保持するという認識でしたが、勝手に更新されてしまうと厄介なことになります。

###試したこと
ある程度調べましたが、そもそもデバッグ実行中にPrefabへ影響を与えるためには特殊な操作が必要という情報しか探せませんでした。
現状は初期値を固定とすることで応急処置していますが最終的には別の方策が必要となります。

何かしら初歩的な思い違いのような気もしますが、自身での対応が限界近くなったためこちらで相談とさせていただきました。
よろしくお願いします。

###補足情報(言語/FW/ツール等のバージョンなど)
Unityのバージョンは5.4.1f1Personalです。

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

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

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

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

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

sakura_hana

2016/11/04 05:08

1.「instanceC」という変数は存在しないようですが、「instanceC0」の間違いでしょうか。 2.念の為Object0とObject1をInstantiateしているコードも提示頂けますでしょうか。 3.「Prefabとして保存されているObject0のメンバinstanceC0まで更新されてしまいます。」とは、具体的にどういう状態でしょうか。(何をもって更新されていると判断したのでしょうか)
guest

回答1

0

ベストアンサー

質問投稿後に何となく分かったような分からないような気がしたので、一応回答投稿しておきます。

■大前提
=で代入したり、setを通してもクラスは全て「参照渡し」になります。

1.最初(インスタンス化された時)
public ClassB instanceB のgetによって、
instanceA0.instanceB.instanceC1 は instanceA0.instanceC0 と同じもの。
instanceA1.instanceB.instanceC1 は instanceA1.instanceC0 と同じもの。
これを(1)とします。

2.instanceA0.instanceB = instanceA1.instanceB; した時
public ClassB instanceB のsetによって、
instanceA0.instanceC0 は instanceA1.instanceB.instanceC1 と同じもの。これを(2)とします。
(1)と(2)から、
instanceA0.instanceC0 は instanceA1.instanceC0 となります。これを(3)とします。

3.instanceA0.instanceC0 = new ClassC(); した時(「instanceC」は「instanceC0」だと仮定)
(3)から、
instanceA1.instanceC0 = new ClassC(); としているのと同義になります。

よって『「instanceA1のメンバーinstanceC0が更新されます。 」とは「instanceA1のメンバーinstanceC0が初期値に戻ります。(new ClassC()された状態になります)」 という意味である』ならば、それは正常な動作です。


■Prefabが更新されている?
仰る通り、『インスタンス化される前の』Prefab(に付いたスクリプト)は通常のスクリプトから変更されません(EditorScriptを書く必要があります)。
逆に言うと、『インスタンス化された後の』Prefab(=Prefabを元にインスタンス化しただけの普通のオブジェクト)は自由に編集可能です。

この辺りの確認をしたく、「何をもって更新されていると判断したのでしょうか」と質問させて頂きました。

投稿2016/11/04 05:40

sakura_hana

総合スコア11427

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

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

eckolo

2016/11/04 14:51

ご回答ありがとうございます。 instanceA0.instanceC0 = new ClassC();で上書きされる現象については理解が追いつきました。下記の件と混同して混乱していたようです。 Prefabに関してですが、インスペクタから確認しています。Projectウィンドウ中のPrefabを選択した状態でInspectorウィンドウの値が更新され、デバック実行終了後もそのままであることを確認しています。 なんとなく今回質問に挙げた以外の部分のコードが影響していそうな気がするのですが、箇所の見当がつきません。こちらの要因となりそうな記述の仕方など心当たりあればご教授願えませんでしょうか。
eckolo

2016/11/05 09:54

あやふやな疑問点に丁寧なご回答ありがとうございます。 PrefabUtilityを直接記述した覚えはありませんが、こちらを軸にもう一度調べ直してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問