CustomPropertyDrawer for Array types in 4.3

I’m trying to implement a drawer for an array type. The closest I can get is by writing a property drawer for the elements it contains, but not for the array (parent).

[CustomPropertyDrawer (typeof (PutOnArraysAttribute))]
// I'll get OnGUI calls for the elements of the array but not for the array itself

This happens on 4.3+. Any ideas?

Create a small System.Serializable nested struct/class within your MonoBehaviour to contain your list:

public class SomeMonoBehaviour : MonoBehaviour
{
	[Serializable] public struct ThingsWrapper {
		public List<string> list;
		
		// optional, for convenience (so you can use ThingsWrapper as if it's a List):
		public static implicit operator List<string>(ThingsWrapper c) { return c.list; }
		public static implicit operator ThingsWrapper(List<string> l) { return new PointsWrapper(){ list = l }; }
	}
	…

Add a field to your MonoBehaviour of this nested ThingsWrapper type adorned with your PutOnArrays attribute:

	…
	[PutOnArrays]
	public ThingsWrapper things;
	…

(Those implicit operators allows your code to keep using the field as if it were an array/list:)

	…
	void Awake() {
		List<string> things = this.things;
		things.Add("hi");
		Debug.Log(things);
	}
	…
} // end of SomeMonoBehaviour

Then, in your PutOnArraysDrawer class, use FindPropertyRelative() to work with the list field:

[CustomPropertyDrawer(typeof(PutOnArraysAttribute))]
public class PutOnArraysDrawer : PropertyDrawer
{
	public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
	{
		property = property.FindPropertyRelative("list");
		
		// …
	}
	
	public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
	{
		property = property.FindPropertyRelative("list");
		
		// …
	}
}

This approach both allows you specify custom attribute/drawers for arrays and for their elements, and keeps those attribute associations within your MonoBehaviour (rather than requiring new class files for each use-case).

If you wanted, I’m sure you wrap up ThingsWrapper into a reusable base class to simplify the code in your class— but it’s really not that much code in the first place. I’ve set up my Attribute to take a listFieldName constructor arg and store it in a property, then my Drawer passes ((PutOnArraysAttribute)this.attribute).listFieldName into FindPropertyRelative() (instead of assuming "list"). Where you go with this is up to you.

I think they should let you put array types into the CustomPropertyDrawer attribute:

[CustomPropertyDrawer(typeof(Hotkey[]))]
public class HotkeysDrawer : PropertyDrawer { ... }

I believe you cannot create a PropertyDrawer for an Array, only an Editor for the containing class and then PropertyDrawers for the members (like you mentioned).

See http://catlikecoding.com/unity/tutorials/editor/custom-list/.