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

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

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

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

Q&A

解決済

1回答

1039閲覧

カスタムエディターの値が保存できない

cc_KH

総合スコア108

Unity

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

0グッド

0クリップ

投稿2022/12/22 13:13

前提

Enumで選択したタイプで継承先のクラスを切り替えようとしています。
オブジェクトにHogeをアタッチし、HogeTypeを変えることでinspectorに表示される変数は変えることはできました。
実行前にHogeType.AでhogeA1に数値を設定しましたが、実行するとcustomHogeに新規でCustomHogeAが割り振られPlay前の値がリセットされてしまいます。

実現したいこと

実行前に設定した値がリセットされないようにしたい

該当のソースコード

using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif public class Hoge : MonoBehaviour { public enum HogeType { A, B } public HogeType hogeType; public CustomHoge customHoge; } public class CustomHoge { } public class CustomHogeA : CustomHoge { public int hogeA1; public bool hogeA2; } public class CustomHogeB : CustomHoge { public float hogeB1; public bool hogeB2; } #if UNITY_EDITOR [CustomEditor(typeof(Hoge))] public class ItemObjectInspector : Editor { public override void OnInspectorGUI() { DrawDefaultInspector(); serializedObject.Update(); Hoge myTarget = (Hoge)target; if (myTarget.customHoge != null) { if (myTarget.hogeType == Hoge.HogeType.A) { if (!(myTarget.customHoge is CustomHogeA)) { Debug.Log("New CustomHogeA"); myTarget.customHoge = new CustomHogeA(); } if (myTarget.customHoge is CustomHogeA) { EditorGUILayout.LabelField("CustomHogeA"); CustomHogeA hoge = (CustomHogeA)myTarget.customHoge; hoge.hogeA1 = EditorGUILayout.IntField("A1", hoge.hogeA1); } } else if (myTarget.hogeType == Hoge.HogeType.B) { if (!(myTarget.customHoge is CustomHogeB)) { Debug.Log("New CustomHogeB"); myTarget.customHoge = new CustomHogeB(); } if (myTarget.customHoge is CustomHogeB) { EditorGUILayout.LabelField("CustomHogeB"); CustomHogeB hoge = (CustomHogeB)myTarget.customHoge; hoge.hogeB1 = EditorGUILayout.FloatField("B1", hoge.hogeB1); } } } else { EditorGUILayout.LabelField("CustomHogeがない"); myTarget.customHoge = new CustomHoge(); } serializedObject.ApplyModifiedProperties(); } } #endif

試したこと

serializedObject.Update();
serializedObject.ApplyModifiedProperties();

補足情報(FW/ツールのバージョンなど)

Unity 2020.3.10f1

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

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

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

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

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

guest

回答1

0

ベストアンサー

SerializeReferenceを使って、たとえば下記のように書いてみるとどうでしょうかね?

C#

1using System; 2using UnityEngine; 3#if UNITY_EDITOR 4using UnityEditor; 5#endif 6 7public class Hoge : MonoBehaviour 8{ 9 public enum HogeType 10 { 11 A, 12 B 13 } 14 public HogeType hogeType; 15 16 // 参照によるシリアル化を行うよう指定 17 // さらに、customHogeはItemObjectInspectorで独自に描画しているので 18 // DrawDefaultInspectorの対象外にするべきかと思い、HideInInspectorも付けました 19 [SerializeReference, HideInInspector] public CustomHoge customHoge; 20} 21 22[Serializable] // シリアル化可能としてマーク 23public class CustomHoge 24{ 25} 26 27[Serializable] // シリアル化可能としてマーク 28public class CustomHogeA : CustomHoge 29{ 30 public int hogeA1; 31 public bool hogeA2; 32} 33 34[Serializable] // シリアル化可能としてマーク 35public class CustomHogeB : CustomHoge 36{ 37 public float hogeB1; 38 public bool hogeB2; 39 40} 41 42#if UNITY_EDITOR 43[CustomEditor(typeof(Hoge))] 44public class ItemObjectInspector : Editor 45{ 46 47 public override void OnInspectorGUI() 48 { 49 DrawDefaultInspector(); 50 serializedObject.Update(); 51 52 Hoge myTarget = (Hoge)target; 53 54 // 変更記録用の処理を用意しておき... 55 void Record() 56 { 57 Undo.RecordObject(myTarget, "Inspector"); 58 EditorUtility.SetDirty(myTarget); 59 } 60 61 if (myTarget.customHoge != null) 62 { 63 if (myTarget.hogeType == Hoge.HogeType.A) 64 { 65 if (myTarget.customHoge is CustomHogeA hoge) 66 { 67 EditorGUILayout.LabelField("CustomHogeA"); 68 69 // customHogeの値を書き換えるときは、値が変更されているか確認して 70 // 変更されていればRecordを行ってから書き換えるようにしました 71 var newValue = EditorGUILayout.IntField("A1", hoge.hogeA1); 72 if (newValue != hoge.hogeA1) 73 { 74 Record(); 75 hoge.hogeA1 = newValue; 76 } 77 } 78 else 79 { 80 Debug.Log("New CustomHogeA"); 81 82 // customHoge自体を差し替えるときにもRecordを行いました 83 Record(); 84 myTarget.customHoge = new CustomHogeA(); 85 } 86 } 87 else if (myTarget.hogeType == Hoge.HogeType.B) 88 { 89 if (myTarget.customHoge is CustomHogeB hoge) 90 { 91 EditorGUILayout.LabelField("CustomHogeB"); 92 93 // ここも同様の処置を行いました 94 var newValue = EditorGUILayout.FloatField("B1", hoge.hogeB1); 95 if (newValue != hoge.hogeB1) 96 { 97 Record(); 98 hoge.hogeB1 = newValue; 99 } 100 } 101 else 102 { 103 Debug.Log("New CustomHogeB"); 104 105 // ここも同様の処置を行いました 106 Record(); 107 myTarget.customHoge = new CustomHogeB(); 108 } 109 } 110 } 111 else 112 { 113 EditorGUILayout.LabelField("CustomHogeがない"); 114 115 // ここも同様の処置を行いました 116 Record(); 117 myTarget.customHoge = new CustomHoge(); 118 } 119 120 serializedObject.ApplyModifiedProperties(); 121 } 122} 123#endif

念のため申し上げますと、後で型名を変更したりするとシリアライズされている型名との不整合が起こって「【Unity】SerializeReferenceに設定したインスタンスのクラス名を変更するとエラーが出る - Qiita」で紹介されているようなトラブルが生じるかもしれません。もしそういった不具合が発生した場合はご遠慮無くコメントください。あいにく私はSerializeReferenceの使用経験が乏しくて自信はないのですが、言い出しっぺの手前ですので復旧に力添えしたく思います。

投稿2022/12/22 19:43

編集2022/12/24 00:43
Bongo

総合スコア10807

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

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

cc_KH

2022/12/23 01:52

ありがとうございます。 [Serializable]を付けることで実行後にリセットされる問題は解消され理想通りの動きになりました。 しかし、指摘されている通り型名を変更するとエラーが発生し、値が保存されない状態(シーンの切替などで確認)になりました。
cc_KH

2022/12/23 03:30

元々テスト用に実行前に値を指定したかっただけですので、別の方法で値を渡すように変更することにしました。 実現したいことは達成できましたのでベストアンサーとさせていただきます。 ありがとうございました。
Bongo

2022/12/24 00:44

もしまた別な場面でSerializeReferenceを使う必要が出てきましたら、その時は最初から型名を仮の名前でなく最終的な名前にしておくのがよさそうですね。仮の名前のままスクリプトをいろいろなオブジェクトにアタッチしてしまうと、後で名前を修正したときに修正する箇所が多くなってしまい復旧がやっかいになりそうです。参考として挙げさせていただいた記事内でも言及されているMovedFromを使えばいくらか楽に修正できるかもしれませんが、それでも後で修正するより最初から名前を確定させておいた方が面倒がなさそうに思います。 それとすみませんが、ItemObjectInspectorに変更を記録する処理を加えるのを失念しておりましたので、回答文中のコードをちょっと修正しました。今回のケースに限らず、スクリプトから値を書き換えたのに変更が反映されない、あるいはシーンを開き直すと元に戻ってしまう...といった症状に遭遇しましたら、可能性の一つとして変更の記録を行っているかを確認してみるといいかと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問