I made a script that allows to append data to a List prop while in Edit Mode. In the inspector in Edit Mode, I can see my list and the data appended to it.
But when I launch Play Mode, the List is cleared and I can see “List is empty”.
I did put [Serializable] on top of the script and on the list field but it doesn’t work.
Here’s the basic code :
#if UNITY_EDITOR
using UnityEditor;
#endif
using System;
using System.Collections.Generic;
using UnityEngine;
using static Helpers.General;
[ExecuteInEditMode]
[SerializeField]
public class SuccessiveJumps : MonoBehaviour {
[Serializable]
public List<JumpZone> jumpZones = new();
//// ------------ CLASSES ----------- ////
[Serializable]
public class JumpZone {
public Vector3 zonePosition;
public Quaternion zoneRotation = Quaternion.identity;
internal JumpZone(Vector3 _zonePosition) {
zonePosition = _zonePosition;
}
}
#if UNITY_EDITOR
public void AddElement() { // There is an editor script that adds a button in the inspector that triggers this method and allows to append data to the list
jumpZones.Add(new JumpZone(Vector3.one));
}
#endif
}
Post the editor script. I bet you’re modifying target directly rather than going through the SerializedObject. Target is a temporary instance in the Editor script that gets thrown away. Only changes to serialized properties are persisted.
The first two Serializable are not needed, only JumpZone needs it. MonoBehaviour is always Serializable, and fields/properties don’t need that attribute but they either have to be public (your case) or have the SerializeField attribute.
Benji23245, Your code should not have compiled because the [SerializeField] attribute should only apply to fields and the [Serializable] attribute should only apply to classes.
You have the opposite here:
[SerializeField]
public class SuccessiveJumps : MonoBehaviour
and here:
[Serializable] public List jumpZones = new();
But overall your code (if you swap the attributes) works fine. I checked in (version 2021.3.14.f1) and when starting the game the fields did not reset their values and after exiting the game everything returned to the expected state (as it was before launch). Everything was also saved after restarting the scene.
I removed a little bit of unnecessary stuff in your code, in my opinion
using System;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class SuccessiveJumps : MonoBehaviour
{
[SerializeField]
public List<JumpZone> jumpZones = new();
public void AddElement()
{
jumpZones.Add(new JumpZone(Vector3.one));
}
//// ------------ CLASSES ----------- ////
[Serializable]
public class JumpZone
{
public Vector3 zonePosition;
public Quaternion zoneRotation = Quaternion.identity;
internal JumpZone(Vector3 _zonePosition)
{
zonePosition = _zonePosition;
}
}
}
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(SuccessiveJumps))]
public sealed class SuccessiveJumpsInspector : Editor
{
private SuccessiveJumps successiveJumps;
private void OnEnable()
{
successiveJumps = target as SuccessiveJumps;
}
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (GUILayout.Button("Add Element")) successiveJumps.AddElement();
}
}
I’m using version 2021.3.20f1, could it be a bug from this version ?
When testing my code, are you sure you just clicked the buttons to add/remove and didn’t manually tweak the list at all (by changing the values/order etc) ?
There is no “remove element” button in your code, but only “Add Element”.
I tried different ways:
just click the “Add Element” button and don’t change anything else manually in the inspector (not field values, not the order of elements, not adding/removing through the “plus/minus” button, which are there by default for the list)
and also manually change everything that could be changed in the inspector of this script
As a result, everything works fine, the values are not reset when the game starts and are restored when the game mode ends.
I have a suspicion that this script is in your prefab, an instance of which you created in the scene? If this is the case, then the data will indeed be reset in game mode. And if this script is added not to the prefab, but simply to an object, then nothing will be reset.
Try adding a method to indicate to the editor that the object has been modified
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(SuccessiveJumps))]
public sealed class SuccessiveJumpsInspector : Editor
{
private SuccessiveJumps successiveJumps;
private void OnEnable()
{
successiveJumps = target as SuccessiveJumps;
}
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (GUILayout.Button("Add Element"))
{
successiveJumps.AddElement();
EditorUtility.SetDirty(successiveJumps); // <--- mark as dirty
}
}
}