2

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.

SagiZiv
  • 932
  • 1
  • 16
  • 38
  • 1
    Possible duplicate of [Constrain dragging to local axis of object](https://stackoverflow.com/questions/22937929/constrain-dragging-to-local-axis-of-object) – Eliasar Aug 06 '19 at 16:18
  • @Eliasar This example doesn't use the mouse cursor at all – SagiZiv Aug 06 '19 at 16:51
  • Is your question about the ability to click and drag and object or to constrain it to a certain axis? The question linked does actually mention the click-to-drag scenario: "Imagine pointing the camera at the face of the cube below, marked with a blue cross (the cursor). You press and hold the mouse to "grab" the cube. The dragging of the cube should now be constrained to the axis, represented with the big red arrow." – Eliasar Aug 06 '19 at 17:00
  • @Eliasar I will check it again soon – SagiZiv Aug 06 '19 at 18:30
  • @SagiZiv see [Compute objects moving with arrows and mouse](https://stackoverflow.com/a/50908533/2521214) in case you re interested how things are done in low level (C++/GL) – Spektre Aug 08 '19 at 07:10

1 Answers1

1

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);
Ruzihm
  • 19,749
  • 5
  • 36
  • 48