SagiZiv
SagiZiv

Reputation: 1040

Drag 3D object on specific axis using the mouse cursor

I am trying to build a simple game, where the user can place some elements and move them around.

What I want is to give the user an option to move the objects on specific axis according to his/her decision.

Pretty much like the movement gizmo in unity.

I know how I can drag an object in the world with the mouse but how can I move on specific axis (e.g. Z axis).

I tried to read the "Mouse X" value, but it only work on a specific viewing angle, if I look at the object from different angle the object won't move correctly.

What I did is this:

private void OnMouseDrag()
{
   transform.Translate(moveAxis * Input.GetAxis("Mouse X");
}

where moveAxis is a Vector3 that represents the axis, and the script is attached to the arrow gizmo.

Upvotes: 2

Views: 1806

Answers (1)

Ruzihm
Ruzihm

Reputation: 20259

Here's one approach:

Convert the moveAxis direction from local space to screen space. Make sure you have a cached Camera field/variable, because calling Camera.main and/or GetComponent<Camera> is a slow operation:

// Get world direction from moveAxis
Vector3 worldDirection = transform.TransformDirection(moveAxis);

Vector2 screenDirection =   camera.WorldToScreenPoint(worldDirection + transform.position) 
                          - camera.WorldToScreenPoint(transform.position);

// optionally, normalize the vector in screen space.
// screenDirection.Normalize();

You can normalize the screen direction if you don't want the angle of the axis on the screen to matter to how fast dragging occurs. You probably don't want to normalize it but give it a try if you want a different feel.

Then, calculate the dot product between the axis direction & the movement of the mouse to calculate a magnitude:

Vector2 mouseMovement = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));

float translateMagnitude = Vector2.Dot(mouseMovement, screenDirection);

mouseMovement.x must be negative for left and positive is right and mouseMovement.y must be negative for down and positive for up. If either axis is inverted, multiply that axis's value by -1f.

This way, translateMagnitude will be positive if the mouse is moved in the direction of the axis in screen space, and negative if it is moved against it.

Then, multiply the magnitude by some configurable sensitivity factor and multiply that by the axis vector for the Translate call:

public float translateSensitivity; 

...

transform.Translate(moveAxis * translateSensitivity * translateMagnitude);

Upvotes: 1

Related Questions