简体   繁体   中英

Why does my object keep rotating even though I tell it to stop at 90 degrees

So, I wrote this code where I tell an object that it should keep rotating until it hits 90 degrees, but it keeps on rotating. Anyway here's the code:

public class playerScript : MonoBehaviour
{
    public float transformZ;
    // Start is called before the first frame update
    IEnumerator Start()
    {
        transformZ = 0;
        transform.position = new Vector3 (0, 0, 0);
        transform.Rotate(0, 0, transformZ);
        while (transformZ != 90)
        {
            transform.Rotate(0, 0, transformZ);
            transformZ = transformZ + 0.1f;
            yield return new WaitForSeconds(0.1f);
        }

        
    }

Any help would be appreciated!

TransformZ is Being Set Wrong

In your function, you are increasing transformZ by itself + 0.1 every 0.1f seconds. Instead of this you should just directly use transform.eulerAngles.z as that provides the exact rotation and you don't need to keep a variable that you increment.

Checking for Exact Inequality

You should not be checking exactly for whether transformZ is not equal to 90, considering this is a float value we are dealing with. There should either be a threshold:

while(Mathf.Abs(90f - transform.eulerAngles.z) < [THRESHOLD])

or you could simply just have the while loop check if its below 90 as Aybe pointed out.

while(transform.eulerAngles.z < 90)

I see various issues here

  • you increase transformZ by 0.1 every 0.1 seconds => this will count seconds, not the actually applied rotation (see further below)

  • you rotate about a value transformZ that is getting bigger each time. Have in mind that Rotate does not set a final rotation but rather starts add the current rotation and adds to it.

    You are rotating like

     Iteration | current rotation | transformZ | resulting rotation 1 | 0 + 0 = 0 2 | 0 + 0.1 = 0.1 3 | 0.1 + 0.2 = 0.3 4 | 0.3 + 0.3 = 0.6 5 | 0.6 + 0.4 = 1.0...
  • then also in general never use == / ! = ! = for floating point values

  • using Rotate there is always the possibility that you overshoot the target rotation

  • and then personally I would prefer a continuous rotation instead of 0.1 second jumps.


A solution depends a bit on what you want to control.

For a fixed rotation per second I would do

[SerializeField] private float anglePerSecond;
[SerializeField] private float maxAngle = 90;

IEnumerator Start() 
{
    ... 

    var initialRotation = transform.rotation;
    // precalculate the desired rotation going through Quaternion instead of directly Euler space 
    var targetRotation = initialRotation * Quaternion.Euler(0, 0, maxAngle);

    // here "Quaternion != Quaternion] uses a lower precise check that allows for small rounding errors
    while (transform.rotation != targetRotation)
    {
        // with linear anglePerSecond rotate towards the final rotation
        // Without ever overshooting the target rotation
        transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, anglePerSecond * Time.deltaTime);
        yield return null;
    }

    // to be sure apply final rotation
    transform.rotation = targetRotation;
}

Or if you rather want to control the duration in seconds

[SerializeField] private float durationInSeconds = 1f;
[SerializeField] private float maxAngle = 90;

IEnumerator Start() 
{
    ... 

    var initialRotation = transform.rotation;
    var targetRotation = initialRotation * Quaternion.Euler(0, 0, maxAngle);

    // similar as before but this time iterate over a certain time
    for(var timePassed = 0f; timePassed < durationInSeconds; timePassed += Time.deltaTime)
    {
        // factor linear growing from 0 to 1
        var factor = timePassed / durationInSeconds;
        // advantage: you can add ease in/out quote easily e.g.
        //factor = Mathf.SmoothStep(0, 1, factor);
        // interpolate via given factor
        transform.rotation = Quaternion.Slerp(initialRotation, targetRotation, factor);
        yield return null;
    }

    transform.rotation = targetRotation;
}

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