So I am trying to serialize a list object so the values within the custom editor stay the same the whole time. But I am having trouble working the logistics of it out
Here is the base code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[System.Serializable]
public class ObjectiveClass {
public string title = "";
public string description = "";
public bool show = true;
}
[AddComponentMenu("Objective Manager"), ExecuteInEditMode]
public class ObjectiveManager : MonoBehaviour {
[SerializeField]
public List<ObjectiveClass>oClass = new List<ObjectiveClass>();
}
Here is the editor code:
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomEditor(typeof(ObjectiveManager))]
public class ObjectiveManager_Editor : Editor {
ObjectiveManager om;
void OnEnable() {
om = target as ObjectiveManager;
}
public override void OnInspectorGUI() {
//UI
foreach (ObjectiveClass oc in om.oClass) {
oc.show = EditorGUILayout.Foldout(oc.show, oc.title.ToString());
if (co.show) {
co.title = EditorGUILayout.TextField("Title", co.title);
co.description = EditorGUILayout.TextField("description", co.description);
}
}
}
}
I recommend removing the CustomEditor for now.
Make sure your Serialization is working properly, from the code above it looks ok.
After that you start on the CustomEditor. As @numberkruncher mentioned, you propabbly want to use SerializedProperties to write your CustomEditor since it will give you Undo functionality and also multi-object selection.
I have searched for a few days over the internet on serialization inside an editor script, that incorporates foreach loops. But I haven’t really found anything, and the stuff I do find is scarcely documented. To be honest i dont really know how to go about using seralization within the script, I have just never needed to use it in an editor script. So the basic understanding I have come across of what I need to do is…
Use SerializedObject on the om.oClass
then Use SerializedProperty for all the values inside om.oClass?
These classes use array elements to create a list or tables. You can create database game , or list of objects from Inspector before running a game, or view objects list at runtime.
I use Lists all the time, and modified one from the Inspector in Edit mode literally just a moment ago. As far as the Inspector is concerned they’re essentially a drop-in replacement for an array.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ListTester : MonoBehaviour {
[SerializeField]
private List<int> testList;
}
If you drop that on a GameObject, does it work? I wonder if you’re not running into issues with one of the other restrictions imposed by Unity’s serialization system.
Had the same problem, which lead to days of coding ugly code and bad design.
Now I revisited the problem and pieces magically fell into place.
This works like a charm:
In your script:
[System.Serializable]
public class GO
{
public string key; // key and name
public GameObject go;
}
[SerializeField]
List<GO> gos = new List<GO>();
In your Editor:
int lineHeight = 16;
public override void OnInspectorGUI()
{
serializedObject.Update();
BlackBoard bb = (BlackBoard)target;
//------------------------------- gos----------------------------------//
var gosProp = serializedObject.FindProperty("gos"); // the list
GUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Add New GameObj");
if (GUILayout.Button("+", GUILayout.Height(lineHeight), GUILayout.Width(20)))
{
bb.AddNew();
}
GUILayout.EndHorizontal();
ShowGOList(gosProp);
serializedObject.ApplyModifiedProperties();
}
void ShowGOList(SerializedProperty list)
{
//
for (int i = 0; i < list.arraySize; i++)
{
EditorGUILayout.BeginHorizontal();
var goProp = list.GetArrayElementAtIndex(i);
var keyProp = goProp.FindPropertyRelative("key");
var gogoProp = goProp.FindPropertyRelative("go");
keyProp.stringValue = EditorGUILayout.TextField(keyProp.stringValue);
gogoProp.objectReferenceValue = EditorGUILayout.ObjectField(gogoProp.objectReferenceValue, typeof(GameObject), true) as GameObject;
if (GUILayout.Button("-", GUILayout.Height(lineHeight), GUILayout.Width(20)))
{
list.DeleteArrayElementAtIndex(i);
i -= 1;
}
EditorGUILayout.EndHorizontal();
}
}
Looks like (I left the ‘More Information’ out of code):
Keypoints are:
In Editor, treat your List<> as if it is an Array (e.g. use list.DeleteArrayElementAtIndex(i);).
Don’t change properties in List directly (aside from creating new Objs). Use FindPropertyRelative() instead and change the property.