- Home /
How to add elements to a SerializedProperty that refernces a List where T : is a Serializable 'regular' class?
Hello,
I have a SerializedProperty
that is referencing a List
, where Decision
is just a regular class (Not a MonoBehaviour
, nor a ScriptableObject
) mocked with [System.Serializable]
The problem I'm facing, I can't add new decisions!
Well, the way one would add something to a list that's referenced via a SerializedProperty
is to manually increase the size of the array (via arraySize
), and then set the last element directly, a method to do that would be (for strings):
public static void Add(this SerializedProperty prop, string value)
{
prop.arraySize++;
prop.GetAt(prop.arraySize - 1).stringValue = value;
}
The problem is that I can't do this to add my Decision
object:
prop.arraySize++;
prop.GetAt(prop.arraySize - 1).objectReferenceValue = value;
Because, objectReferenceValue
is a UnityEngine.Object
, while Decision
is a System.Object
There's no way to convert from the first to the second.
There are obvious ways around this, one to make the Decision
class a ScriptableObject
that way it is a UnityEngine.Object
, other is to just get a direct reference to the list and just add the element - but then I would have to register undo manually.
I would really love to just keep my class a normal class, and be able to add it to the list via the SerializedProperty
Any ideas?
Thanks!
Answer by vexe · Feb 14, 2014 at 10:22 PM
Found the solution! - I was just watching this video for the 3rd time maybe, when I noticed @29:40, he's just incrementing the arraySize
to add a new entry. But then I said oh well, that's because the entry is probably a ScriptableObject
, but... surprise surprise @30:19 - it's a normal class!
Couple of things to take note of:
Doing a size increment like that will duplicate the last element in the array/list.
If after the increment you wanted to 'directly' access the element you added, you have to do a
serializedObject.ApplyModifiedProperties();
so that the change will get reflected on the actual target object.Not a horrible thing to notice, but you should put the initialization logic of your object (in my case
Decision
) in its constructor since you can't really get a reference to it via theSerializedProperty
to call someInit
method (if there's a method you'd want to call, you have to call it directly like(target as MyClass).Field.Method();
)
So yeah that's about it, arraySize++
Heya @vexe this is cool, thanks for sharing
Anyway i wonder... How can i perform List.Remove(index) with the _serializedProperty...
Because if i try to do
_serializedProperty.DeleteArrayElementAtIndex(index)
It removes the reference of the index, but doesn't actually removes the index, but leaves it empty...
The only way i found, doing it is by moving the index to the last position and then do arraySize--:
if (_serializedProperty.GetArrayElementAtIndex(index).objectReferenceValue != null)
_serializedProperty.DeleteArrayElementAtIndex(index);
_serializedProperty.$$anonymous$$oveArrayElement(index, _serializedProperty.arraySize -1);
_serializedProperty.arraySize--;
I was wondering if there is another way...
@instruct9r Yeah I remember that. Another way is to call DeleteArrayElementAtIndex twice on the same index, second time's the charm! Another way is to forget about SerializedProperties altogether, and don't use them. Awful API.
As always, thanks for your very insightful answers! They need you on the Unity documentation $$anonymous$$m to write details like these :P
@vexe as of Unity 2019.1.9f1 this see$$anonymous$$gly does not work. :C Whenever you increment on the next call to OnGUI the property is indeed not updated. Really annoying actually unless i am missing something. I already tried prop.serializedObject.Apply$$anonymous$$odifiedProperties as well
Your answer
Follow this Question
Related Questions
How to iterate through all serialized property children ( deep search ) 1 Answer
Replicate "Apply" and "Revert" button functionality in ScriptableObject Editor Inspector 2 Answers
Can UnityEvent data be transferred to/from a ScriptableObject? 0 Answers
Override Transform Inspector using SerializedObject and SerializedProperty 1 Answer
Serializedproperty assignment 2 Answers