Home > Enterprise >  Trigonometry Angles - Object rotating around player and facing mouse direction
Trigonometry Angles - Object rotating around player and facing mouse direction

Time:12-03

I do not understand how this code works and I am seeking an explanation. This code is inside an update function, updating the Objects location constantly.

By "facing the mouse direction" I mean that the object is like the earth orbiting around the sun for example, but you choose where it is currently located on it's rotation line around the sun.

     public GameObject player;
     private Vector3 v3Pos;
     private float angle;
     private readonly float distance = 0.16f;
 
     private void Update()
     {
         v3Pos = Input.mousePosition;
         v3Pos.z = (player.transform.position.z - 
        Camera.main.transform.position.z);
         v3Pos = Camera.main.ScreenToWorldPoint(v3Pos);
         v3Pos -= player.transform.position;
         angle = Mathf.Atan2(v3Pos.y, v3Pos.x) * Mathf.Rad2Deg;
         if (angle < 0.0f) { angle  = 360.0f; }
         transform.localEulerAngles = new Vector3(0, 0, angle);
 
         float xPos = Mathf.Cos(Mathf.Deg2Rad * angle) * distance;
         float yPos = Mathf.Sin(Mathf.Deg2Rad * angle) * distance;
         transform.localPosition = new Vector3(player.transform.position.x   
         xPos * 4, player.transform.position.y   yPos * 4, 0);
     }

I found this code in a video which makes an object (like a gun) rotate around the player and follow the mouse simultaneously but I don't understand how it works. How does it work? Also, I don't know where the video is at any more but I will find it if necessary.

CodePudding user response:

It warps the attached gameobject so many units in the direction of the mouse cursor from the player (locally for some reason), and also turns to face its right side in that direction (locally for some reason).

Individual sections explained in the comments below:

public GameObject player;
private Vector3 v3Pos;
private float angle;
private readonly float distance = 0.16f;

private void Update()
{
    // mouse position in screen space 
    // current value = (mouse x, mouse y, 0) )
    Vector3 v3Pos = Input.mousePosition;

    // sets the z coordinate to be the difference from the camera to the player
    //   along the forward world axis.
    // current value = (mouse x, mouse y, camera->player distance along forward)
    v3Pos.z = (player.transform.position.z - Camera.main.transform.position.z);

    // v3Pos now means the position of the cursor, projected onto plane the player
    // is on parallel to camera plane
    // This means it's a world space positioning of the mouse
    v3Pos = Camera.main.ScreenToWorldPoint(v3Pos);

    // v3Pos now means the direction from the player to the mouse position 
    //   in world space.
    // Despite the name, now a direction, not a position!
    v3Pos -= player.transform.position;

    // finds the signed angle from right to the direction v3Pos represents.
    // in the range (-180, 180]. positive = counterclockwise
    angle = Mathf.Atan2(v3Pos.y, v3Pos.x) * Mathf.Rad2Deg;

    // converts negative angle into an equivalent positive angle.
    if (angle < 0.0f) { angle  = 360.0f; }

    // sets the forward axis angle of the transform this 
    //   MonoBehaviour is attached to as the same angle.
    // Since we measured from the right to the direction of the mouse, 
    //   this turns the right side to face the mouse.
    // This is done in local space for some reason, can't tell from code.
    transform.localEulerAngles = new Vector3(0, 0, angle);
 
    // finds x and y coordinates of a point in the same direction as 
    //   v3Pos the mouse from the player but at distance 
    // Could use v3Pos but with a z=0, normalized then * distance but 
    //   recalculating with trig works too.
    float xPos = Mathf.Cos(Mathf.Deg2Rad * angle) * distance;
    float yPos = Mathf.Sin(Mathf.Deg2Rad * angle) * distance;

    // sets the player's local position to be the position of the player 
    //   adjusted by the direction and distance of the point.
    // Also done in local space, can't tell why from code.
    // Weird to use something else's world position as the local position
    //   for something else.
    transform.localPosition = new Vector3(player.transform.position.x  
               xPos * 4, player.transform.position.y   yPos * 4, 0);
 }

CodePudding user response:

The steps are

// Get the mouse position on the screen
v3Pos = Input.mousePosition;
// Bring that point down until it is level with the player
v3Pos.z = (player.transform.position.z - Camera.main.transform.position.z);
// Find that point in world space coordinates
v3Pos = Camera.main.ScreenToWorldPoint(v3Pos);
// Find the vector from the player to that point
v3Pos -= player.transform.position;
// Calculate the angle between that vector and the X axis
angle = Mathf.Atan2(v3Pos.y, v3Pos.x) * Mathf.Rad2Deg;
// ensure the values are between 0 and 360
if (angle < 0.0f) { angle  = 360.0f; }
// Set the item's rotation to that angle, so it faces the right direction
transform.localEulerAngles = new Vector3(0, 0, angle);
// Find the new position of the item on the orbit circle
float xPos = Mathf.Cos(Mathf.Deg2Rad * angle) * distance;
float yPos = Mathf.Sin(Mathf.Deg2Rad * angle) * distance;
// Set the item to it's new position
transform.localPosition = new Vector3(player.transform.position.x   xPos * 4, player.transform.position.y   yPos * 4, 0);

I'm not sure why the coordinates in that last step are multiplied by 4, they should already be positioned on a circle with radius distance

  • Related