I’m creating an “Expose” field attribute using UI Toolkit (CreatePropertyGUI from PropertyDrawer). Its purpose is to expose an object’s field (serialized property) in the inspector without having to travel to the object to edit it. I will mainly use this attribute to directly edit ScriptableObjects while a MonoBehaviour is selected.
I’ve managed to successfully code this using IMGUI - the older editor UI system; but, I’m reaching an unexpected issue with UI Toolkit.
Basic code explanation:
- Create root VIsualElement;
- Create, setup and add a normal PropertyField;
- Get an UXML file for the custom Foldout;
- Query and set up the Foldout;
- Create a SerializedObject based on the PropertyDrawer’s property object reference value;
- Iterate through every SerializedObject’s properties and copy them to an array (ignores some properties);
- Use this array to create and add PropertyFields; ← The add is where the error is coming from!
The PropertyDrawer class:
```csharp
*using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
[CustomPropertyDrawer(typeof(ExposeAttribute))]
public class ExposeAttributePropertyDrawer : PropertyDrawer
{
private VisualElement _root;
private SerializedProperty _serializedProperties;
private const string k_foldoutUxmlGuid = "c370dc7d5a39e92428503c5c195c612b";
private static string s_foldoutUxmlPath;
private static string FoldoutUxmlPath
{
get
{
if (string.IsNullOrEmpty(s_foldoutUxmlPath))
s_foldoutUxmlPath = AssetDatabase.GUIDToAssetPath(k_foldoutUxmlGuid);
return s_foldoutUxmlPath;
}
}
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
_root = new VisualElement();
var propField = new PropertyField(property);
propField.BindProperty(property);
_root.Add(propField);
if (property.objectReferenceValue == null)
return _root;
var foldoutUxml = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(FoldoutUxmlPath);
var foldoutRoot = foldoutUxml.Instantiate();
var foldout = foldoutRoot.Q<Foldout>();
foldout.text = $"Edit \"{property.objectReferenceValue.name}\"";
using var serializedObject = new SerializedObject(property.objectReferenceValue);
GetProperties(serializedObject);
if (foldout.value)
{
for (int i = 0; i < _serializedProperties.Length; i++)
{
var prop = _serializedProperties[i];
var propPropField = new PropertyField(prop);
propPropField.BindProperty(prop);
// The next line of code doesn't work.
// If I comment the next line of code, the error goes away.
foldoutRoot.Add(propPropField);
}
}
_root.Add(foldoutRoot);
serializedObject.ApplyModifiedProperties();
return _root;
}
private void GetProperties(SerializedObject serializedObject)
{
serializedObject.UpdateIfRequiredOrScript();
var prop = serializedObject.GetIterator();
if (!prop.Next(true))
return;
int currentPropIndex = 0;
List<SerializedProperty> serializedProperties = new();
do
{
if (currentPropIndex > 9)
serializedProperties.Add(prop.Copy());
currentPropIndex++;
}
while (prop.Next(false));
_serializedProperties = serializedProperties.ToArray();
}
}*
```
The error:
The error doesn’t directly point to line 60, but when removing it, the error gets never printed. I tried to add the PropertyFields to other VisualElements and the error gets printed anyway. The IMGUI version does literally the same thing, but it works (take this into account; I may post the IMGUI code if necessary).
Am I missing something? Thank you.