三角学 + 角度 - 围绕玩家旋转并面向鼠标方向的对象

Trigonometry + Angles - Object rotating around player and facing mouse direction

我不明白这段代码是如何工作的,我正在寻求解释。此代码位于更新函数内,不断更新对象位置。

我所说的“面向鼠标方向”是指该物体就像地球围绕太阳公转一样,但是您可以选择它当前位于它围绕太阳的自转线上的位置。

     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);
     }

我在一段视频中发现了这段代码,它使一个物体(如枪)围绕玩家旋转并同时跟随鼠标,但我不明白它是如何工作的。它是如何工作的?另外,我不知道视频在哪里,但如果需要我会找到它。

它使附加的游戏对象在玩家鼠标光标的方向上扭曲这么多单位(由于某种原因在局部),并且还转向面向该方向的右侧(由于某种原因在局部)。

个别部分在下面的评论中解释:

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.
    // basic trig refresher
    //   cos of angle from right gives unit circle x coordinate
    //   sin of angle from right gives unit circle y coordinate
    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);
 }

上面提到的替代计算可以这样完成:

    Vector3 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.eulerAngles = new Vector3(0, 0, angle);

    Vector3 v3DirFlat = v3Pos;
    v3DirFlat.z = 0f;
    // keeping both * distance and * 4 
    v3DirFlat = v3DirFlat.normalized * distance * 4; 
    transform.position = player.transform.position + v3DirFlat;

步骤是

// 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);

我不确定为什么最后一步的坐标乘以 4,它们应该已经位于半径为 distance

的圆上