всплывающее поле в пользовательском редакторе сбрасывается при игре - PullRequest
0 голосов
/ 05 декабря 2018

Попытка кодирования для пользовательского редактора, но значение выпадающего или всплывающего поля всегда сбрасывается при нажатии кнопки воспроизведения.

Я просмотрел несколько похожих вопросов и нашел решения по добавлению, применяя измененные и установив грязные, но оба этого не сделалирешить проблему.

Есть идеи, что может произойти?

Вот код ниже:

[CustomEditor(typeof(EnemyAI))]
public class Level_SelectionEditor : Editor
{
    string[] _choices = new[] { "snailer", "sheller" };
    int _choiceIndex = 0;

    override public void OnInspectorGUI()
    {



        // Draw the default inspector
        var mc = target as EnemyAI;



        EditorGUILayout.PropertyField(serializedObject.FindProperty("damage"), true);
       EditorGUILayout.PropertyField(serializedObject.FindProperty("attackCounter"), true);

        EditorGUILayout.PrefixLabel("Type");
        EditorGUI.indentLevel++;
        _choiceIndex = EditorGUILayout.Popup(_choiceIndex, _choices);



        //updated in code
        if (_choices[_choiceIndex] == "snailer")
        {
            mc.type = EnemyAI.Type.snailer;

            EditorGUILayout.PropertyField(serializedObject.FindProperty("snailerEffect"), true);
            EditorGUILayout.PropertyField(serializedObject.FindProperty("snailerShootPoint"), true);
        }
        else
        {
            mc.type = EnemyAI.Type.sheller;
            EditorGUILayout.PropertyField(serializedObject.FindProperty("rotationsPerMinute"), true);
            EditorGUILayout.PropertyField(serializedObject.FindProperty("rotationTime"), true);
            EditorGUILayout.PropertyField(serializedObject.FindProperty("pauseTime"), true);
        }



        // Save the changes back to the object
        EditorUtility.SetDirty(target);

        serializedObject.ApplyModifiedProperties();




    }
}

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Прежде всего: не объединяйте

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 целевого класса.Это не хорошо по другим трем причинам:

  1. сценарий редактора не будет скомпилирован в сборку -> это значение не будет доступно
  2. у вас нет доступа к немузначение также не из вашего фактического класса -> для чего оно лучше?
  3. , даже если это только контрольное значение для содержимого внутри редактора: это значение будет сбрасываться при каждой инициализации сценария редактора,Это происходит

    • после каждой перекомпиляции
    • после входа или выхода из режима воспроизведения
    • каждый раз, когда соответствующий объект получает фокус

Для сохранения этого значения вы должны поместить _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);

Таким образом, некоторые из моих правил забора выглядят как

  1. всегда, если вы хотите изменить / сохранить значения, используйте SerlialzedProperty.Иногда бывает сложно заставить их работать (особенно, например, со списками или вложенными классами), и вы можете легко совершать ошибки, так как вы получаете их по имени переменной (строка).Но они приносят много преимуществ, таких как автоматическая маркировка материала как грязного, отмена / повтор и т. Д.

  2. только причина для использования target as <some type> для прямого доступа к материаламбыть вызванным методом класса изнутри редактора (предпочтительный, который не изменяет ни одно из сериализованных значений).Но также и здесь: используйте это только в том случае, если это действительно необходимо, потому что, как уже упоминалось, смешивание SerializedProperty и прямых изменений часто приводит к путанице.

  3. переменные должны вводиться только в инспекторе, если

    • вы не заинтересованы в их сохранении
    • они должны сбрасываться каждый раз, когда Инспектор теряет фокус
    • они являются постоянными значениями, которые вы никогда не измените (например, метки дляполя или ваш choices массив)

и последний общий совет:

вы должны использовать serializedObject.FindProperty не во всех вызовах отрисовки.скорее соберите все свои свойства один раз в OnEnable() как

SerializedProperty _type;
// ...

private void OnEnable()
{
    _type = serializedObject.FindProperty("type");
    // ...
}

public override void OnInpectorGUI()
{
    // ...
    EditorGUILayout.PropertyField(_type);
    // ...
}
0 голосов
/ 05 декабря 2018

Вы должны определить свойство choiceIndex и базовое значение в классе EnemyAI, а затем установить его в EditorScript следующим образом:

mc.choiceIndex = EditorGUILayout.Popup(mc.choiceIndex, _choices);

Также в операторе if:

 if (_choices[mc.choiceIndex] == "snailer"){
     ...
 }

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...