Skip to content

Instantly share code, notes, and snippets.

@mminer
Last active Sep 28, 2021
Embed
What would you like to do?
Unity attribute to make Vector3 and Vector3[] fields draggable in the scene.
using UnityEngine;
/// <summary>
/// Attribute to add to Vector3 and Vector3[] fields to make them draggable in the scene.
/// </summary>
public class Draggable : PropertyAttribute
{
}
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
/// <summary>
/// Makes Vector3 and Vector3[] fields decorated with the Draggable attribute draggable in the scene.
/// </summary>
[CustomEditor(typeof(MonoBehaviour), true)]
public class DraggableEditor : Editor
{
void OnSceneGUI()
{
if (Tools.current != Tool.Move)
{
return;
}
var transform = ((MonoBehaviour)target).transform;
using (new Handles.DrawingScope(transform.localToWorldMatrix))
{
foreach (var property in GetPropertiesWithDraggableAttribute())
{
if (property.propertyType == SerializedPropertyType.Vector3)
{
Vector3Handle(property, property.name);
}
else if (property.isArray && property.arrayElementType == nameof(Vector3))
{
for (var i = 0; i < property.arraySize; i++)
{
var element = property.GetArrayElementAtIndex(i);
Vector3Handle(element, $"{property.name}[{i}]");
}
}
}
}
}
IEnumerable<SerializedProperty> GetPropertiesWithDraggableAttribute()
{
var targetObjectType = serializedObject.targetObject.GetType();
var property = serializedObject.GetIterator();
while (property.Next(true))
{
var field = targetObjectType.GetField(property.name);
if (field != null && Attribute.IsDefined(field, typeof(Draggable)))
{
yield return property.Copy();
}
}
}
void Vector3Handle(SerializedProperty property, string labelText)
{
Handles.Label(property.vector3Value, labelText);
property.vector3Value = Handles.PositionHandle(property.vector3Value, Quaternion.identity);
serializedObject.ApplyModifiedProperties();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment