简体   繁体   中英

Rotate 2D object linearly

My 2D object is looking up ( transform.up = (0,1) ).

When I click somewhere in the screen, I want the object to look to where I clicked. I also want it to rotate linearly: it should rotate d degrees per second, implying that it takes twice the time to rotate twice the angle.

Here is my code:

void Update() {
    if (Input.GetMouseButtonDown(0)) {
        Vector2 wPos = cameraRef.ScreenToWorldPoint(Input.mousePosition);
        StartCoroutine(LookAt(mouseScreenPosition));
    }   
}

public IEnumerator LookAt(Vector2 position) {
    Vector2 direction = (position - (Vector2) transform.position).normalized;
    float angle = Vector2.SignedAngle(direction, transform.up);
    float startAngle = transform.eulerAngles.z;

    for(float t = 0; t <= 1; t += Time.deltaTime * (180 / Mathf.Max(1, Mathf.Abs(angle)))) {
        transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(startAngle, startAngle - angle, t));
        yield return null;
    }
}

The factor I multiply Time.deltaTime is 180 / Mathf.Max(1, Mathf.Abs(angle)) , which says that the bigger the angle, the bigger the time it takes to rotate, but I don't know if I'm doing it right (it works) or if this is the better way to do it.

Define some rotationSpeed field:

public float rotationSpeed = 90f;

Use Quaternion.LookRotation to get the Quaternion you want to rotate towards. You want the local forward to point in the global forward direction and local up to point towards the target position, so use Quaternion.LookRotation(Vector3.forward,targetDirection) :

public IEnumerator LookAt(Vector2 position) {
    // casting to Vector2 and normalizing is redundant
    Vector3 targetDirection = position - transform.position; 
    Quaternion targetRotation = Quaternion.LookRotation(Vector3.forward, targetDirection);

Then use Quaternion.RotateTowards with the max amount of degrees you want to rotate in that frame until you are done rotating toward the goal rotation:

while (Quaternion.Angle(targetRotation, transform.rotation) > 0.01) 
{
    transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation,
            time.deltaTime * rotationSpeed);
}

Altogether:

public float rotationSpeed = 90f;

public IEnumerator LookAt(Vector2 position) {
    // casting to Vector2 and normalizing is redundant
    Vector3 targetDirection = position - transform.position; 
    Quaternion targetRotation = Quaternion.LookRotation(Vector3.forward, targetDirection);

    while (Quaternion.Angle(targetRotation, transform.rotation) > 0.01) 
    {
        transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation,
                time.deltaTime * rotationSpeed);
    }
}

You could use Quaternion.Lerp: https://docs.unity3d.com/ScriptReference/Quaternion.Lerp.html

I think that's what you're looking for?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM