Is there a better way to code this custom-propertydrawer?

using UnityEngine;
using UnityEditor;
using System.Collections;

[CustomPropertyDrawer (typeof (UnityTest01.Marker3))]

public class MarkerDrawer : PropertyDrawer {

    public override void OnGUI (Rect pos, SerializedProperty prop, GUIContent label)
    {
        float newX = EditorGUIUtility.labelWidth + 14;
        EditorGUI.PrefixLabel(pos, label);

        //Draw Checkboxes on the Inspector
        EditorGUI.PropertyField(new Rect(newX, pos.y, 28, pos.height), prop.FindPropertyRelative("x"), GUIContent.none);
        EditorGUI.LabelField(new Rect(newX + 14, pos.y, 16, pos.height), "X");
        newX += 30;
        EditorGUI.PropertyField(new Rect(newX, pos.y, 28, pos.height), prop.FindPropertyRelative("y"), GUIContent.none);
        EditorGUI.LabelField(new Rect(newX + 14, pos.y, 16, pos.height), "Y");
        newX += 30;
        EditorGUI.PropertyField(new Rect(newX, pos.y, 28, pos.height), prop.FindPropertyRelative("z"), GUIContent.none);
        EditorGUI.LabelField(new Rect(newX + 14, pos.y, 16, pos.height), "Z");
    }
}

What I want is:

LABEL…[-]X [-]Y [-]Z

XYZ checkboxes much like RigidbodyConstraints but only a single row of it.

The problem:
I’m unable to align the property fields with the default inspector field indent. So I had to resort to this ‘14’ which is a value i found by trial and error, I’m sure there’s a better way to do it.
The labels don’t get highlighted, only the prefixlabel and only for the first checkbox.
I’ve tried using toggle, but it ends up readonly, unlike propertyfield.

This is my first attempt at property drawer. I would appreciate any kind of help.

like most EditorGUI and EditorGUILayout field functions, EditorGUI.Toggle (and EditorGUI.ToggleLeft) return the changed value. They don’t directly change the property like PropertyField does. so you need to pass their results back into the property

Your question is subjected to opinion as to whats “truly” better, since such code typically revolves around opinion
here is how I would write such a class (not tested mind you since I don’t actually have the class to draw)

[CustomPropertyDrawer(typeof(UnityTest01.Marker3),true)]
public class MarkerDrawer : PropertyDrawer
{
   // some fields I make static because they would be the same for all instances of the Drawer

   // nearly all of my fields in any Editor script follows the same notation:
   // k_: is reserved for key names that would be used in FindProperty, 
   //       FindRelativeProperty, and my Extension GetProperty
   // c_: is reserved for GUIContent and string labels
   // p_: is reserved for each individual SerializedProperty used
   // r_: is reserved by all Rect
   // there are several others that I may use but are not relevant to this class

   //property key names
    private static string k_xMarker   = "x";
    private static string k_yMarker   = "y";
    private static string k_zMarker   = "z";

    // the content I'll use for all drawer instances
    private static GUIContent c_xMarker = new GUIContent("X");
    private static GUIContent c_yMarker = new GUIContent("Y");
    private static GUIContent c_zMarker = new GUIContent("Z");

    //used serialized properties
    private SerializedProperty p_xMarker;
    private SerializedProperty p_yMarker;
    private SerializedProperty p_zMarker;

    override public float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return EditorGUIUtility.singleLineHeight+4f;
    }

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        //GetProperty is an extension method
        p_xMarker = property.GetProperty(k_xMarker);
        p_yMarker = property.GetProperty(k_yMarker);
        p_zMarker = property.GetProperty(k_zMarker);


        Rect r_fields = label.PrefixLabel(position);//this Prefix Label is an extension Method
        Rect r_xMarker = new Rect (r_fields.xMin,  r_fields.yMin,50,r_fields.height);
        Rect r_yMarker = new Rect (r_xMarker.xMax, r_fields.yMin,50,r_fields.height);
        Rect r_zMarker = new Rect (r_yMarker.xMax, r_fields.yMin,50,r_fields.height);

        EditorGUI.BeginChangeCheck ();
            // remember most EditorGUI/EditorGUILayout return their values. 
            // boolean is a value type and must be set back manually 
            p_xMarker.boolValue = EditorGUI.ToggleLeft(r_xMarker,c_xMarker,p_xMarker.boolValue);
            p_yMarker.boolValue = EditorGUI.ToggleLeft(r_yMarker,c_yMarker,p_yMarker.boolValue);
            p_zMarker.boolValue = EditorGUI.ToggleLeft(r_zMarker,c_zMarker,p_zMarker.boolValue);

        if(EditorGUI.EndChangeCheck())
            property.serializedObject.ApplyModifiedProperties();
        
    }
        
}

in this example I’ve used a couple extension methods to help simplify the code (only slightly). my typical Editor Scripts uses a ton of extension methods to add alot of code sugar to them

 public static class PropertyDrawerExtensions
    {
        //GetProperty genericizes SerializedObject.FindProperty and 
        // SerializedProperty.FindPropertyRelative to one identical call
        // it will also handle the special case where it fails to find the 
        // property for SerializedObject classes
        public static SerializedProperty GetProperty(this SerializedObject serializedObject,string k_field)
        {
            return serializedObject.FindProperty (k_field);
        }
        public static SerializedProperty GetProperty(this SerializedProperty property,string k_field)
        {
            if (property == null)
                throw new ArgumentNullException ("property must not be null");
    
            if(string.IsNullOrEmpty(k_field))
                throw new ArgumentException("Field name must not be null or empty");
    
            SerializedProperty relative = property.FindPropertyRelative (k_field);
            if (relative != null)
                return relative;
    
            // if the passed in property is a ScriptableObject then 
            // FindPropertyRelative won't work, you need cast a new serializedObjet
            SerializedObject SO = new SerializedObject(property.objectReferenceValue);
            relative = SO.FindProperty (k_field);
    
    
            if (relative != null)
                return relative;
    
            //if relative is null then throw exception because it won't 
            // be obvious to the user what broke in their Editor scripts 
            // if null was simply returned
            throw new ArgumentException(string.Format("Could not find the relative property \"{0}\"",k_field));
        }
    
        public static Rect PrefixLabel(this GUIContent c_content, Rect r_total)
        {
            if(c_content==null || c_content== GUIContent.none)
                return r_total;
    
    
            Vector2 size = GUI.skin.label.CalcSize(c_content);
    
            Rect r_label = new Rect(r_total.xMin, r_total.yMin, size.x + 15f,                  r_total.height);
            Rect r_field = new Rect(r_label.xMax, r_total.yMin, r_total.width - r_label.width, r_total.height);
    
            EditorGUI.LabelField(r_label,c_content);
    
            return r_field ;
        }
    }