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

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

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

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

Unity

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

Q&A

解決済

1回答

1418閲覧

【Unityエディタ拡張】OnInspectorGUI()内でbool型SerializedPropertyの値がfalseからtrueになった時だけ処理をするコードについて質問

tammat

総合スコア1

C#

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

Unity

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

0グッド

0クリップ

投稿2021/09/25 04:13

編集2021/09/25 15:07

こちらのエディタ拡張について解説している動画のこの部分で
https://youtu.be/j4eMvdgXAHw?t=1442
SerializedPropertyとして宣言した overrideAttackMessageProp の値で
bool prevOverrideAttackMessage を初期化し、
その後二行後のif文内でこちらのプロパティをオフ(false)→オン(true)にした瞬間(エディタ内でチェックボックスにチェックを入れた瞬間)に何らかの処理をする
というコードがありますが、

C#

1 2 // public override void OnInspectorGUI()内の処理です 3 4 bool prevOverrideAttackMessage = overrideAttackMessageProp.boolValue; 5 EditorGUILayout.PropertyField(overrideAttackMessageProp, overrideAttackMessageLabel); 6 if (overrideAttackMessageProp.boolValue) 7 { 8 if (!prevOverrideAttackMessage) 9 { 10 // オフ → オンになった時に親の攻撃メッセージを取ってくる 11 attackMessageProp.stringValue = parent.AttackMessage; 12 } 13 14 // 上書きをするなら書き換え 15 EditorGUILayout.PropertyField(attackMessageProp, attackMessageLabel); 16 }

■OnInspectorGUI()が最初に呼ばれた時、
overrideAttackMessageProp.boolValue:false
prevOverrideAttackMessageがfalseで初期化される

■overrideAttackMessageProp.boolValue:trueになった時にOnInspectorGUI()が呼ばれた時
overrideAttackMessageProp.boolValue:true
bool prevOverrideAttackMessage = overrideAttackMessageProp.boolValue;
によって
prevOverrideAttackMessageもtrueになってしまうはずと考えました。
よって、prevOverrideAttackMessageの初期化の行が無視されなければ

C#

1 if (overrideAttackMessageProp.boolValue) 2 { 3 if (!prevOverrideAttackMessage) 4 { 5 //この中に入ることはできないのでは???????? 6 } 7 }

と思ったのですが、OnInspectorGUI()の中で変数の初期化が記述されている場合、
最初の呼び出し以降は無視される仕様となっているのでしょうか?

MonoBehaviour の Update() 内では変数の初期化は毎フレーム行われると思いますが、
こちらとどのような違いがあるために、このような挙動をするのでしょうか?

また、そもそも「初期化の一行が無視されている」という考えから間違っているのでしょうか?

こちらの動画投稿者さんが動画説明欄であげてくださっている全文ソースをこちらに引用させていただきます。
https://github.com/ina-amagami/ScriptableObject-Sample/blob/master/Assets/Scripts/Section4/Editor/BreedInspector.cs

こちらでは一部の抜粋のみの掲載で大変恐縮ですが、よろしければご教授いただけますよう何卒よろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

Unityの組み込みUI(IMGUI)は、ちょっと特殊でとっつきにくいのですが…。

overrideAttackMessageProp.boolValue:trueになった時にOnInspectorGUI()が呼ばれた時

ここが間違いの元ではないかと思います。
ユーザからの操作などの処理は、全てEditorGUILayout.PropertyFieldメソッドの中で行われます。
ですので、overrideAttackMessageProp.boolValue:trueになるのは、PropertyFieldメソッドの中です。

csharp

1 // public override void OnInspectorGUI()内の処理です 2 3 // 直前の値を記録しておく。 4 bool prevOverrideAttackMessage = overrideAttackMessageProp.boolValue; 5 // ユーザ操作があれば、メソッドの中でプロパティの値が変更される。 6 EditorGUILayout.PropertyField(overrideAttackMessageProp, overrideAttackMessageLabel); 7 if (overrideAttackMessageProp.boolValue) 8 { 9 if (!prevOverrideAttackMessage) 10 { 11 // 直前の値がfalseで、現在がtrueである。 12 // つまり、PropertyFieldの中で値が変更された。 13 // イコール、ユーザ操作によってtrueにされたと判断する。 14 } 15 }

MonoBehaviour の Update() 内では変数の初期化は毎フレーム行われると思いますが、
こちらとどのような違いがあるために、このような挙動をするのでしょうか?

UnityEditor.Editor.OnInspectorGUIUnityEngine.MonoBehaviour.OnGUIなどは、EventType(マニュアル)で定義されているイベントが発生した際に呼ばれます。
(何となく描画する際に呼ばれる、と思われがちだが、マウスなどの入力でも呼ばれる)

投稿2021/09/25 15:14

katsuko

総合スコア3538

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

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

tammat

2021/09/25 16:05 編集

稚拙な内容の質問にも関わらず、丁寧にご回答いただき、大変感激いたしました。誠にありがとうございます。 ユーザー操作と、SerializedPropertyへの反映タイミングについてよく理解できました。 続けて大変恐縮なのですが、「EditorGUILayout.PropertyFieldメソッドの中でプロパティの値が変更される」根拠はどういった情報からご学習されていらっしゃるのでしょうか? https://docs.unity3d.com/ja/current/ScriptReference/EditorGUILayout.PropertyField.html こちらのマニュアルを熟読したのですが、そういった(実際にプロパティに値を代入するタイミングについての)情報を読み取ることができません。今回の場合、どういった資料を探して学習するべきだったのでしょうか? 本当にもしよろしければ、ご教授いただけますと幸いに存じます。
katsuko

2021/09/25 16:32

一応言っておきますが、自信満々に回答してますが、少しは憶測も入ってますよ(笑) ただもちろん、その憶測も経験からくる知識から、ほぼ間違いないだろうと思って書いています。 例えば、EditorGUILayoutの他のメソッドを見てください。ほとんどが、現在の値を引数として渡し、変更された値を戻り値として返します。 これはつまり、ユーザによる操作(による値の変更)も、メソッド内で処理されている、と考えられます。 (自分で実装するとどうなるか、を考えると、そのようになっているとしか思えない) とすれば、PropertyFieldも例外ではないでしょう。 また、EventTypeに関しては、以前「エディタ拡張でドラッグ&ドロップするにはどうしたらいいのだろう」と調べた際に得た知識だと思います。 (かなり前なので当時参考にしたサイトではないかもですが、例えば下のサイトでの説明でも、EventTypeを扱ってます) https://warapuri.com/post/24185933889/unity-inspector-editor%E4%B8%8A%E3%81%ABdragdrop%E3%81%97%E3%81%9F%E3%81%84 ちなみに、UnityEditorモジュールのソースコードは、公開されています。 https://github.com/Unity-Technologies/UnityCsReference ただ、自分は途中でめんどくさくなって、追うのを止めました。
tammat

2021/09/25 16:59 編集

早急にご回答いただきありがとうございます! >「EditorGUILayoutの他のメソッドを見てください」 なるほど!!数個読んできましたが、確かに同クラスの他のメソッドの挙動を調査することで、目的のメソッドの挙動の予測を立てることができますね、、、!!とても勉強になります。 katsuko様のようなご経験豊富な方から大変貴重な「考え方」についてのコメントを頂けたこと、大変嬉しく、今後の学習の励みになります!EventTypeについての記事や、UnityEditorソースコードのご共有についても、本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問