Сериализация списка пользовательских объектов в единстве - PullRequest
0 голосов
/ 02 октября 2018

При попытке создать сценарий для создания ресурсов я столкнулся с проблемой сериализации Unity.У меня есть класс, в котором я храню некоторую произвольную информацию, которая затем сохраняется в массиве в MonoBehaviour на префабе.Однако я не могу получить массив для сохранения, так как когда я превращаю объект в префаб, он теряет значения списка.Я пытался использовать [System.Serializable] и ScriptableObject, но оба, похоже, создают свои собственные новые проблемы.

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

Я ошибаюсь вмое понимание сериализации единства?Есть ли способ заставить это работать без подхода ScriptableObject сохранения каждого объекта ArbitraryInfo в активе?

Объект данных:

[System.Serializable]
public class ArbitraryInfo{
    public int intValue;
    public Vector3 vectorValue;
}

ИЛИ

public class ArbitraryInfo : ScriptableObject {
    public int intValue;
    public Vector3 vectorValue;

    void OnEnable() {
        hideflags = HideFlags.HideAndDontSave;
    }
}

Поведение:

public class MyBuilder : MonoBehaviour {
    public ArbitraryInfo[] infoArray;
}

Редактор:

[CustomEditor(typeof(MyBuilder))]
public class MyBuilderEditor : Editor {
    private SerializedProperty infoArrayProperty;

    void OnLoad() {
        infoArrayProperty = serializedObject.FindProperty("infoArray");
    }

    void OnInspectorGUI() {
        serializedObject.Update();

        for (var i = 0; i < infoArrayProperty.arraySize; i++) {
            if (i > 0) EditorGUILayout.Space();

            var info = infoArrayProperty.GetArrayElementAtIndex(i).objectReferenceValue as ArbitraryInfo;

            EditorGUILayout.LabelField("Info " + i, EditorStyles.boldLabel);

            info.intValue = EditorGUILayout.IntField(info.intValue);
            info.vectorValue = EditorGUILayout.Vector3Field(info.vectorValue);
        }

        serializedObject.ApplyModifiedProperties();
    }
}

РЕДАКТИРОВАТЬ 1, Спасибо derHugo

Я изменил свой код, чтобы включить изменения.Теперь есть ошибки для ArbitraryInfo, который не является поддерживаемым значением pptr.

Во-вторых, ArbitraryInfo, более не являющийся объектом ScriptableObject, ставит вопрос о том, как его инициализировать.Пустой объект может быть добавлен к infoArrayProperty - infoArrayProperty.arraySize++, но этот новый пустой объект в моем случае кажется пустым.Это может быть связано с проблемой pptr, упомянутой выше.

РЕДАКТИРОВАТЬ 2

Проблема, с которой я столкнулся, была вызвана другим фрагментом кода, где я пытался проверить, если infoArrayProperty.objectReferenceValue == null.Я изменил это на другую проверку, которая сделала то же самое, и все работало!

1 Ответ

0 голосов
/ 02 октября 2018

Нет, ScriptableObject не требуется.

Но учтите, что GetArrayElementAtIndex(i) возвращает SerializedProperty.Вы не можете просто разобрать его в своем целевом классе.

, поэтому вместо

var info = infoArrayProperty.GetArrayElementAtIndex(i).objectReferenceValue as ArbitraryInfo;

и

info.intValue = EditorGUILayout.IntField(info.intValue);
info.vectorValue = EditorGUILayout.Vector3Field(info.vectorValue);

вы должны получить info 's SerializedProperty с использованием FindPropertyRelative:

var info = infoArrayProperty.GetArrayElementAtIndex(i);

var intValue = info.FindPropertyRelative("intValue");
var vectorValue = info.FindPropertyRelative("vectorValue");

, чем вы можете / должны использовать PropertyField с

EditorGUILayout.PropertyField(intValue);
EditorGUILayout.PropertyField(vectorValue);

всегда старайтесь избегать использования прямых сеттеров и используйте вместо этого эти SerializedProperties!Это дает вам возможность отмены / повтора и помечает измененное поведение / сцену как несохраненные автоматически.В противном случае вам придется позаботиться об этом вручную (... не надо ^^).

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