Editor拡張ではSerializedPropertyを使おう。
UnityのEditor拡張は便利だが、よく紹介されているEditorGUILayout.FloatValue()などの直接値を返すものを使用すると、Prefabモードでは値が反映されない。 その場合は、SerializedProperty経由のEditorGUILayout.PropertyFieldを使うと、Prefabモードでも正しく値が反映される。
以下のようなEditor拡張はサンプルとしてもよく見ると思う。
using UnityEngine; using UnityEditor; public class EditorSample1 : MonoBehaviour { public float a; public GameObject b; #if UNITY_EDITOR [CustomEditor(typeof(EditorSample1))] class InternalEditor : Editor { EditorSample1 _self; private void OnEnable() { _self = target as EditorSample1; } public override void OnInspectorGUI() { _self.a = EditorGUILayout.FloatField(_self.a); _self.b = EditorGUILayout.ObjectField(_self.b, typeof(GameObject), false) as GameObject; } } #endif }
このコンポーネントをアタッチすると、Projectビューから直接選択した場合には問題なく編集することができる。
しかしUnity2018.3から追加されたPrefabモードでは値を変更することができない。
代わりにSerializedObjectからSerializedPropertyを取得して、EditorGUILayout.PropertyField()を使用するように変更する。 (Editorクラスのみ抜粋)
[CustomEditor(typeof(EditorSample1))] class InternalEditor : Editor { EditorSample1 _self; SerializedObject _sObj; private void OnEnable() { _self = target as EditorSample1; _sObj = serializedObject; } public override void OnInspectorGUI() { var propA = _sObj.FindProperty("a"); var propB = _sObj.FindProperty("b"); EditorGUILayout.PropertyField(propA); EditorGUILayout.PropertyField(propB); if(_sObj.hasModifiedProperties) { _sObj.ApplyModifiedProperties(); } } }
これによりPrefabモードでも値を変更することができる。