[SOLVED] Handles.DoPositionHandle: Associate With GameObject Transform ?

How do I associate a Handles.DoPositionHandle with a GameObject Transform such that the DoPositionHandle will appear at the GameObject’s position and the inspector field will read 0:0:0 ?

Currently I have only been able to figure out how to Draw the Handle at WorldSpace 0:0:0
In the following image, the cube is at WorldSpace 1:0:1. You’ll note the Handles at 0:0:0
2902079--213673--handles.png

I am able to calculate the actual the offset position, but am unsure how to reflect this in the inspector, as any calculations I make in OnGUI have compounding results… That is, the Handles quickly fly off screen.

What I want to be able to do is:

Draw the Handles starting at the Cube’sTransform Position and reflect a position of 0:0:0 in the inspector…
As I move the handles, the Position field should update to reflect the distance from the Cube.
Conversely, As I change the inspector values, the the handles should move in relation to the Cube

Can someone help correct my code?
Thanks

using UnityEditor;
using UnityEngine;

public class Mover : EditorWindow
{
    private GameObject _gameObject;
    private Vector3 _handleVector;
    private Vector3 _postionVector;
    private Vector3 _distanceVector;

    [MenuItem("Tools/Mover")]
    public static void OpenWindow()
    {
        var window = GetWindow<Mover>();
        window.titleContent = new GUIContent("Mover");
    }

    protected void OnEnable()
    {
        SceneView.onSceneGUIDelegate += OnSceneGUI;
    }

    protected void OnDisable()
    {
        SceneView.onSceneGUIDelegate -= OnSceneGUI;
    }

    protected void OnGUI()
    {
        EditorGUILayout.BeginVertical();
        _gameObject = (GameObject)EditorGUILayout.ObjectField("Game Object", _gameObject, typeof(GameObject), true);
        _postionVector = EditorGUILayout.Vector3Field("Position", _postionVector);
        _distanceVector = EditorGUILayout.Vector3Field("Distance to Game Object", _distanceVector);
        EditorGUILayout.EndVertical();
    }

    protected void OnInspectorUpdate()
    {
        if (SceneView.lastActiveSceneView != null)
        {
            SceneView.lastActiveSceneView.Repaint();
        }

        _handleVector = _postionVector;
        _distanceVector = GetDistanceVector(_gameObject.transform.position, _handleVector);


    }

    protected void OnSceneGUI(SceneView sceneview)
    {

        if (_gameObject)
        {
            EditorGUI.BeginChangeCheck();
            _handleVector = Handles.DoPositionHandle(_handleVector, Quaternion.identity);


            if (EditorGUI.EndChangeCheck())
            {
                _postionVector = _handleVector;
                _distanceVector = GetDistanceVector(_gameObject.transform.position, _handleVector);
            }
        }

        Repaint();

    }

    private Vector3 GetDistanceVector(Vector3 v1, Vector3 v2)
    {
        return new Vector3(Mathf.Abs(v1.x - v2.x), Mathf.Abs(v1.y - v2.y), Mathf.Abs(v1.z - v2.z));
    }



}

You will need to transform from and to the object’s local coordinate system.

Check out the public functions starting with Transform and InverseTransform.

Hey! If you know how to do this, don’t be coy. Because… believe me … I know what a “Transform” is.
Vector math is not my problem. The lackluster documentation is.

Solved with a bool.

Here’s The Code if it helps anyone:

using UnityEditor;
using UnityEngine;

public class Mover: EditorWindow
{
    private Vector3 _differenceVector;
    private GameObject _gameObject;
    private Vector3 _handleVector;
    private bool _isSet;
    private Vector3 _postionVector;

    private float _relativeX;
    private float _relativeY;
    private float _relativeZ;


    [MenuItem("Tools/Mover")]
    public static void OpenWindow()
    {
        var window = GetWindow<Mover>();
        window.titleContent = new GUIContent("Mover");
    }

    protected void OnEnable()
    {
        SceneView.onSceneGUIDelegate += OnSceneGUI;
    }

    protected void OnDisable()
    {
        SceneView.onSceneGUIDelegate -= OnSceneGUI;
    }

    protected void OnGUI()
    {
        EditorGUILayout.BeginVertical();
        _gameObject = (GameObject)EditorGUILayout.ObjectField("Game Object", _gameObject, typeof(GameObject), true);
        _postionVector = EditorGUILayout.Vector3Field("Position", _postionVector);

        if (_gameObject)
        {
            _differenceVector = _gameObject.transform.position * -1;
        }

        EditorGUILayout.EndVertical();
    }

    protected void OnInspectorUpdate()
    {
        if (SceneView.lastActiveSceneView != null)
        {
            SceneView.lastActiveSceneView.Repaint();
        }

        if (DetectChange(_postionVector, new Vector3(_relativeX, _relativeY, _relativeZ)))
        {
            _relativeX = _postionVector.x - _differenceVector.x;
            _relativeY = _postionVector.y - _differenceVector.y;
            _relativeZ = _postionVector.z - _differenceVector.z;

            _handleVector = new Vector3(_relativeX, _relativeY, _relativeZ);
        }

        if (!_gameObject)
        {
            _isSet = false;
        }
          
    }

    protected void OnSceneGUI(SceneView sceneview)
    {
        if (_gameObject)
        {
            EditorGUI.BeginChangeCheck();
            if (!_isSet)
            {
                _handleVector = Handles.DoPositionHandle(_gameObject.transform.position, Quaternion.identity);
                _isSet = true;
            }
            else
            {
                _handleVector = Handles.DoPositionHandle(_handleVector, Quaternion.identity);
            }

            if (EditorGUI.EndChangeCheck())
            {
                _postionVector = _handleVector + _differenceVector;
                _relativeX = _postionVector.x;
                _relativeY = _postionVector.y;
                _relativeZ = _postionVector.z;
            }
        }

        Repaint();
    }

    private bool DetectChange(Vector3 v1, Vector3 v2)
    {
        return !Mathf.Approximately(v1.x, v2.x) || !Mathf.Approximately(v1.y, v2.y) || !Mathf.Approximately(v1.z, v2.z);
    }
1 Like

@FuguFirecracker
Whoa Nelly!

That is some complicated code right there. I was having the same issue and I think I have found a much better solution. I know this was asked almost a year ago but I hope you come back and see this.

Basically when I am placing the handle, when I am calling the PositionHandle or DoPositionHandle method and I give the vector3 argument i also add the position of the object the component is on. THEN after i have called the PositionHandle method I subtract the objects position from it again!

Code is from a thing I am working on. Too lazy to change the variable names to match yours haha, so sorry about that. Just pay attention to the line in OnSceneGUI.

[CustomEditor(typeof(AttackSequence))]
public class HitBoxDrawer : Editor
{
    AttackSequence obj;

    private void OnEnable()
    {
        obj = (AttackSequence) target;
    }

    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();
    }

    private void OnSceneGUI()
    {
        obj.hBox.centre = Handles.PositionHandle(obj.hBox.centre + obj.transform.position, Quaternion.identity) - obj.transform.position;
    }
4 Likes

Hey! Thanks for the post… That does seem much simpler :wink:

idc if this thread is 2 years old, thank u this was exactly what i was trying to figure out!!

Thank you for this! You just saved me a lot of time!
Edit: Still relevant and efficient.