Прежде всего: не объединяйте
EditorUtility.SetDirty(target);
serializedObject.ApplyModifiedProperties();
Старайтесь никогда не смешивать SerialzedProperties
, и я называю это "прямыми" свойствами (используя target
)!Это может привести к множеству неприятностей.
Вы также звоните
serializedObject.ApplyModifiedProperties();
, но я не вижу, куда вы звоните
serializedObject.Update();
, чтобы получить актуальныйсначала значения.
Также я думаю, что комментарий там не принадлежит
// Draw the default inspector
var mc = target as EnemyAI;
по крайней мере, это не то, что там происходит.
Наконец, причина вашегозначение для сброса заключается в том, что вы вводите _choiceIndex
в сценарии редактора, поэтому ни serialzedObject.ApplyModifiedProperties()
, ни EditorUtility.SetDirty(target)
не будут влиять на него, так как он не является SerializedField целевого класса.Это не хорошо по другим трем причинам:
- сценарий редактора не будет скомпилирован в сборку -> это значение не будет доступно
- у вас нет доступа к немузначение также не из вашего фактического класса -> для чего оно лучше?
, даже если это только контрольное значение для содержимого внутри редактора: это значение будет сбрасываться при каждой инициализации сценария редактора,Это происходит
- после каждой перекомпиляции
- после входа или выхода из режима воспроизведения
- каждый раз, когда соответствующий объект получает фокус
Для сохранения этого значения вы должны поместить _choiceIndex
в класс EnemyAI, но почему бы просто не использовать ваше перечисление EnemyAI.Type
или лучше сказать уже существующее поле type
вместо этого?Предполагая
[SerialzeField] private EnemyAI.Type type;
в вашем редакторе сценария, вы можете просто сделать
// This automatically also uses the label "Type"
EditorGuyLayout.PropertyField(serializedObject.FindProperty("type"));
, а также
if ((EnemyAI.Type)_choiceIndex.intValue == EnemyAI.Type.snailer)
В качестве альтернативы, если вы предпочитаете придерживатьсясписок строк, например, для заполнения дополнительных опций выбора через скрипт редактора, вы можете сделать то же самое с помощью int, но также используя SerializedProperty
.
In EnemyAI
[SerializeField] private int _choiceIndex;
И в редакторе
SerializedProperty _choiceIndex = serialzedObject.FindProperty("_choiceIndex");
_choiceIndex.intValue = EditorGuyLayout.Popup("Type", _choiceIndex.intValue, choices);
Таким образом, некоторые из моих правил забора выглядят как
всегда, если вы хотите изменить / сохранить значения, используйте SerlialzedProperty
.Иногда бывает сложно заставить их работать (особенно, например, со списками или вложенными классами), и вы можете легко совершать ошибки, так как вы получаете их по имени переменной (строка).Но они приносят много преимуществ, таких как автоматическая маркировка материала как грязного, отмена / повтор и т. Д.
только причина для использования target as <some type>
для прямого доступа к материаламбыть вызванным методом класса изнутри редактора (предпочтительный, который не изменяет ни одно из сериализованных значений).Но также и здесь: используйте это только в том случае, если это действительно необходимо, потому что, как уже упоминалось, смешивание SerializedProperty и прямых изменений часто приводит к путанице.
переменные должны вводиться только в инспекторе, если
- вы не заинтересованы в их сохранении
- они должны сбрасываться каждый раз, когда Инспектор теряет фокус
- они являются постоянными значениями, которые вы никогда не измените (например, метки дляполя или ваш
choices
массив)
и последний общий совет:
вы должны использовать serializedObject.FindProperty
не во всех вызовах отрисовки.скорее соберите все свои свойства один раз в OnEnable()
как
SerializedProperty _type;
// ...
private void OnEnable()
{
_type = serializedObject.FindProperty("type");
// ...
}
public override void OnInpectorGUI()
{
// ...
EditorGUILayout.PropertyField(_type);
// ...
}