Version: 2021.3+
This example demonstrates how to use the binding-path attribute of a BindableElement in UXML to bind fields to nested properties of a SerializedObject.
This example creates a custom Inspector UI with the following:
 
You can find the completed files that this example creates in this GitHub repository.
This guide is for developers familiar with the Unity Editor, UI Toolkit, and C# scripting. Before you start, get familiar with the following:
Create a C# script to define a class for a tank that has health values to make it destructible.
Create a project in Unity with any template.
In your Project window, create a folder named bind-nested-properties to store all the files.
Create a C# script named DestructibleTankScript.cs and replace its content with the following:
using System;
using UnityEngine;
using UnityEngine.Serialization;
[Serializable]
public struct Health
{
    public int armor;
    public int life;
}
[ExecuteInEditMode]
public class DestructibleTankScript : MonoBehaviour
{
    public string tankName = "Tank";
    public float tankSize = 1;
    public Health health;
    private void Update()
    {
        gameObject.name = tankName;
        gameObject.transform.localScale = new Vector3(tankSize, tankSize, tankSize);
    }
    public void Reset()
    {
        health.armor = 100;
        health.life = 10;
    }
}
Create a UXML file with a BindableElement. Set the BindableElement’s binding-path to the health property and set each child element’s binding-path of the BindableElement to the armor and life properties of health.
In the bind-nested-properties folder, create a folder named Editor.
In the Editor folder, create a USS file named tank_inspector_styles.uss and replace its contents with the following:
.container {
    background-color: rgb(80, 80, 80);
    flex-direction: column;
}
Label {
    background-color: rgb(80, 80, 80);
}
TextField:hover {
    background-color: rgb(255, 255, 0);
}
FloatField {
    background-color: rgb(0, 0, 255);
}
Create a UI Document named destructible_tank_editor.uxml and replace its contents with the following:
<UXML xmlns="UnityEngine.UIElements" xmlns:ue="UnityEditor.UIElements">
    <Style src="tank_inspector_styles.uss"/>
    <VisualElement name="row" class="container">
        <Label text="Tank Script - Custom Inspector" />
        <ue:PropertyField binding-path="tankName" name="tank-name-field" />
        <ue:PropertyField binding-path="tankSize" name="tank-size-field" />
        <BindableElement binding-path="health">
            <ue:PropertyField binding-path="armor"/>
            <ue:PropertyField binding-path="life"/>
        </BindableElement>
    </VisualElement>
</UXML>
Create a C# script that registers a custom Editor for the DestructibleTankScript. 
Create a C# script named DestructibleTankEditor.cs and replace its content with the following:
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
[CustomEditor(typeof(DestructibleTankScript))]
public class DestructibleTankEditor : Editor
{
    [SerializeField]
    VisualTreeAsset visualTreeAsset;
    public override VisualElement CreateInspectorGUI()
    {
        return visualTreeAsset.CloneTree();
    }
}
Select DestructibleTankEditor.cs in the Project window.
Drag destructible_tank_editor.uxml to Visual Tree Asset in the Inspector. 
health.armor and health.life properties. If you change the values in the Inspector, the values of the underlying properties change.