当通过 angularVelocity 将 2D 精灵旋转到光标时,它会在一点旋转

When rotating 2D sprite towards cursor via angularVelocity, it spins at one point

简介

我在我的 Unity 项目中创建了一个宇宙飞船精灵,我希望它通过 angular 速度向光标旋转,因为我想让我的游戏非常基于物理。

问题

现在我通过 angular 速度 旋转 sprite 的问题如下:

在 -180° / 180° 旋转时,我的船旋转,因为虽然我的鼠标 angle 已经是 180°,而我的船 rotation 仍然是 -180°,反之亦然。

我试过了

我试图用数学方法解决它,不太成功,我可以让它以正确的方式旋转 slower/faster,我可以修复 180/-180 点,但是做了两个不同的点.

寻找了不同的解决方案,但找不到更合适的解决方案。

代码

所以我有这个旋转代码:

// Use this for initialization
void Start () {
    rb = gameObject.GetComponent<Rigidbody2D>();
}

// Update is called once per frame
void Update () {
    //getting mouse position in world units
    mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);

    //getting the angle of the ship -> cursor vector
    angle = Mathf.Atan2(mousePos.y - transform.position.y, mousePos.x - transform.position.x) * Mathf.Rad2Deg;

    //getting the angle between the ship -> cursor and the rigidbody.rotation vector
    diffAngle = angle - (rb.rotation + 90);

    //Increasing angular velocity scaling with the diffAngle
    rb.angularVelocity = diffAngle * Time.deltaTime * PlayerShipStats.Instance.speed * 100f;

提前感谢您的投稿

问题 1 的解决方案

插入此代码使其工作,不会太久 :

if(diffAngle > 180) {
        diffAngle -= 360;
    } else if (diffAngle < -180) {
        diffAngle += 360;
    }

问题 2 和问题 2 的解决方案

新问题是: rigidbody.rotation可以越界,可以旋转360度以上

此代码修复了此错误:

if(rb.rotation + 90 >= 180) {
            rb.rotation = -270;
        } else if (rb.rotation + 90 <= -180) {
            rb.rotation =  90;
        }

完美代码

void AimAtTarget(Vector2 target, float aimSpeed) {

    //getting the angle of the this -> target vector
    float targetAngle = Mathf.Atan2(target.y - transform.position.y, target.x - transform.position.x) * Mathf.Rad2Deg;

    if (rb.rotation + 90 >= 180) {
        rb.rotation = -270;
    } else if (rb.rotation + 90 <= -180) {
        rb.rotation = 90;
    }

    //getting the angle between the this -> target and the rigidbody.rotation vector
    float diffAngle = targetAngle - (rb.rotation - 90);

    if (diffAngle > 180) {
        diffAngle -= 360;
    } else if (diffAngle < -180) {
        diffAngle += 360;
    }

    //Increasing angular velocity scaling with the diffAngle
    rb.angularVelocity = diffAngle * Time.deltaTime * aimSpeed * 100;
}

我在这里看到两个问题:

问题 1

angle 始终介于 -180 和 180 之间,而 rb.rotation 介于 0 和 360 之间。因此您使用两种不同的表示法比较角度。第一步是让两个角度都返回 -180 到 180 或 0 到 360。我选择执行以下操作,将两个角度都放在 -180 和 180 之间:

//getting the angle of the ship -> cursor vector
float targetAngle = Mathf.Atan2(
    mousePos.y - transform.position.y, 
    mousePos.x - transform.position.x) * Mathf.Rad2Deg;

//get the current angle of the ship
float sourceAngle = Mathf.Atan2(
    this.transform.up.y, 
    this.transform.up.x) * Mathf.Rad2Deg;

问题2

如果您解决了问题 1 并尝试了您的应用程序,您会注意到飞船有时会以错误的方式旋转,尽管它最终会到达目标。问题是 diffAngle 有时会给出大于 +180 度(或小于 -180)的结果。当发生这种情况时,我们实际上希望飞船向另一个方向旋转。该代码如下所示:

//getting the angle between the ship -> cursor and the rigidbody.rotation vector
float diffAngle = targetAngle - sourceAngle;

//use the smaller of the two angles to ensure we always turn the correct way
if (Mathf.Abs(diffAngle) > 180f)
{
    diffAngle = sourceAngle - targetAngle;
}

我制作了一个简单的 Unity 来验证它是否有效。我能够顺利地向任一方向旋转我的船。

您可能需要处理的一件事(如果您还没有处理的话)是当飞船面向光标时适当地停止飞船的旋转。在我的测试中,我注意到飞船在到达目标时会轻微抖动,因为它会(非常)在一个方向上然后在另一个方向上稍微超过光标的角度。 PlayerShipStats.Instance.speed 的值越大,这种效果可能越明显。