The documentation for creating a custom inspector (Unity - Manual: Create a Custom Inspector) suggests that this is how the PropertyDrawer for the Tire array should render in the inspector:
However, when I attempt the same thing, using the code provided in the documentation, I get a different result, which has reorderable handles, reorderable containers, a foldout, a toggle, a scroll view (if the array is expanded using the add/subtract buttons)…etc.:
Point being, there’s a lot present that the documentation doesn’t even so much as suggest, and I’m driving myself to the brink of insanity trying to figure out how to remove these things so that my end-product matches the documentation’s result. I can see all of these elements in the UI Debugger as children of the PropertyField that gets bound to m_Tires (or myTires, in my case; see image below), but I don’t seem to be able to access them at all, in any way, to be able to remove them. That said, I have a few questions:
1. What methods can I use to get mine to match Unity’s?
2. Why doesn’t the documentation reflect or address this disparity in results?
Thank you for looking into updating the screenshots. In the meantime, would you or anyone else be able to provide more guidance related to removing the other unwanted functionality from the result?
As an example, I’ve tried various iterations of the following without finding success:
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;
using UnityEditor.UIElements;
using System.Collections.Generic;
[CustomPropertyDrawer(typeof(TireSpecs))]
public class TirePropertyDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var container = new VisualElement();
VisualTreeAsset myInspectorUXML = Resources.Load<VisualTreeAsset>("Editor/UXML/Car_Inspector_UXML.uxml");
if (myInspectorUXML != null)
{
VisualElement parentContainer = myInspectorUXML.CloneTree();
if (parentContainer != null )
{
PropertyField propertyField = parentContainer.Q<PropertyField>("my-property-field");
if (propertyField != null )
{
propertyField.Bind(property.serializedObject);
container.Add(parentContainer);
return container;
}
else
{
Debug.LogError("PropertyField not found in UXML hierarchy.");
}
}
else
{
Debug.LogError("Failed to clone UXML hierarchy.");
}
}
else
{
Debug.LogError("Failed to load UXML file.");
}
var popup = new UnityEngine.UIElements.PopupWindow();
popup.text = "Tire Details";
popup.Add(new PropertyField(property.FindPropertyRelative("airPressure"), "Air Pressure (psi): "));
popup.Add(new PropertyField(property.FindPropertyRelative("profileDepth"), "Profile Depth (mm): "));
container.Add(popup);
return container;
}
}
Hi,
You will need to either bind directly to a ListView or get the ListView the PropertyField is using and make changes. If you want the one the PropertyFIeld is using you will need to wait until it has done its own binding and created it, so maybe add a delay and then do propertyField.Q<ListView>()
Thank you! If it wouldn’t be a huge imposition, I appear to be doing something wrong in my script that is causing Unity to enter an infinite loop or something, and I cannot figure out what that might be.
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;
using UnityEditor.UIElements;
using System.Collections.Generic;
[CustomPropertyDrawer(typeof(TireSpecs))]
public class TirePropertyDrawer : PropertyDrawer
{
public CarInspector carInspector;
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var container = new VisualElement();
VisualTreeAsset myInspectorUXML = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Resources/UXML/Car_Inspector_UXML.uxml");
if (myInspectorUXML != null)
{
VisualElement parentContainer = myInspectorUXML.CloneTree();
if (parentContainer != null)
{
PropertyField propertyField = parentContainer.Q<PropertyField>("my-property-field");
if (propertyField != null)
{
propertyField.Bind(property.serializedObject);
container.Add(parentContainer);
EditorApplication.delayCall += () => OnDelayCall(propertyField);
var popup = new UnityEngine.UIElements.PopupWindow();
popup.text = "Tire Details";
popup.Add(new PropertyField(property.FindPropertyRelative("airPressure"), "Air Pressure (psi): "));
popup.Add(new PropertyField(property.FindPropertyRelative("profileDepth"), "Profile Depth (mm): "));
container.Add(popup);
return container;
}
else
{
Debug.LogError("PropertyField not found in UXML hierarchy.");
}
}
else
{
Debug.LogError("Failed to clone UXML hierarchy.");
}
}
else
{
Debug.LogError("Failed to load UXML file.");
}
return base.CreatePropertyGUI(property);
}
private void OnDelayCall(PropertyField propertyField)
{
if (propertyField != null)
{
Debug.Log("PropertyField Hierarchy: " + propertyField.hierarchy);
Debug.Log("PropertyField Children Count: " + propertyField.childCount);
// Loop through children and log their types and names
foreach (var child in propertyField.Children())
{
Debug.Log("Child Type: " + child.GetType());
Debug.Log("Child Name: " + child.name);
}
ListView listView = propertyField.Q<ListView>();
if (listView != null)
{
Debug.Log(listView.hierarchy);
//do stuff here
}
else
{
Debug.LogWarning("ListView component not found in the PropertyField.");
}
}
}
}