0

So, in my scene I have my main game object, and a second game object which serves as a reference. I want the main game object to rotate so that it will face the same way as the second game object. And this rotating needs to happen in a set time. Let's presume the duration is 3 seconds. If the second game object has a world rotation of 0, 90, 0, the main game object starts to rotate so that after three seconds it's rotation is 0, 90, 0.

So, I have the Transforms of the main game object and the second game object, now I need to calculate the amount to rotate per frame, so that the rotation happens in the correct duration.

I would very much appreciate it if someone could help me! Thank you in advance.

  • Could you maybe add some images that show what happens and then what you would like to have happen instead? That gives us a clearer idea of what's going on. – HoloLady Apr 29 '20 at 13:11

4 Answers4

1

Whenever you want something moving within a specified time I would recommend to not do it in Update but instead use a Coroutine. It works like a little temporary Update method and is executed each frame until the next yield. this is better to maintain and control than the Update method.

Then do your rotation using Quaternion.Lerp or also Quaternion.Slerp depending a bit on your needs

private IEnumerator RotateOverTime(Transform transformToRotate, Quaternion targetRotation, float duration)
{
    var startRotation = transformToRotate.rotation;

    var timePassed = 0f;
    while(timePassed < duration)
    {
        var factor = timePassed / duration;
        // optional add ease-in and -out
        //factor = Mathf.SmoothStep(0, 1, factor);

        transformToRotate.rotation = Quaternion.Lerp(startRotation, targetRotation, factor);
        // or
        //transformToRotate.rotation = Quaternion.Slerp(startRotation, targetRotation, factor);

        // increae by the time passed since last frame
        timePassed += time.deltaTime;

        // important! This tells Unity to interrupt here, render this frame
        // and continue from here in the next frame
        yield return null;
    }

    // to be sure to end with exact values set the target rotation fix when done
    transformToRotate.rotation = targetRotation;
}

Now in order to start this routine you would call it via StartCoroutine like e.g.

// simply stop any other running routine so you don't get concurrent ones
StopAllCoroutines();
StartCoroutine(transformToRotate, otherTransform.rotation, 3f);
derHugo
  • 83,094
  • 9
  • 75
  • 115
  • This is EXACTLY what I needed! It takes account the duration and the target rotation! Thank you sir, you have cured my headache. – TomatoBird Apr 28 '20 at 12:48
1

You can use Slerp method for this. So, it should be something like this in Update:

transform.rotation = Quaternion.Slerp(transform.rotation, secondTransform.rotation, rotationSpeed * Time.deltaTime);
Onurcan Onder
  • 496
  • 2
  • 6
0

https://answers.unity.com/questions/765197/how-do-i-rotate-an-object-over-a-set-time.html

The answer for short:

 float totalRotationTime = 5.0f;
 float y_degreesPerSecond = go.transform.eulerAngles.y / totalRotationTime;
 float x_degs = go.transform.x/ totalRotationTime;
 //etc...
 go.transform.Rotate(new Vector3(x_degs * Time.deltaTime, degreesPerSecond * Time.deltaTime, 0));
barbecu
  • 684
  • 10
  • 28
  • what if `Y` is not the only axis to be rotated? – derHugo Apr 28 '20 at 12:17
  • Then do the same calculations for x and z and replace the first zero with that value, Edited it for you with an example – barbecu Apr 28 '20 at 12:21
  • or simply do `Vector3 rotationPerSecond = go.transform.eulerAngles / totalRotationTime;` and `go.transform.Rotate(rotationPerSecond * Time.deltaTime);` ;) – derHugo Apr 28 '20 at 12:22
0

I have updated the answer given by derHugo, with this update you can define the time and the angle that object will rotate in the given time.

    private IEnumerator RotateOverTime(float duration)
    {
        var timePassed = 0f;
        while (timePassed < duration)
        {
            var factor = timePassed / duration;

            factor = (Mathf.PI / 2) * (Time.deltaTime / duration);
            print("factor: " + factor);

            hedefAraYon = Vector3.RotateTowards(transform.forward, hedefYon, factor, 0.0f);
            transform.rotation = Quaternion.LookRotation(hedefAraYon, Vector3.back);

            // increae by the time passed since last frame
            timePassed += Time.deltaTime;

            // important! This tells Unity to interrupt here, render this frame
            // and continue from here in the next frame
            yield return null;
        }        
        
        // donme takılı kalabiliyor, o yüzden 0,5f olarak ayarladım
        if (Quaternion.Angle(transform.rotation, Quaternion.LookRotation(hedefYon, Vector3.back)) <= 0.5f)
        {
            Vector3 tempRotation = transform.rotation.eulerAngles;
            tempRotation.x = Mathf.RoundToInt(tempRotation.x);
            tempRotation.y = Mathf.RoundToInt(tempRotation.y);
            tempRotation.z = Mathf.RoundToInt(tempRotation.z);
            transform.rotation = Quaternion.Euler(tempRotation);
        }

        hareketDurumu = HAREKET_DURUMU.DURUYOR;
        print("Time Passed-Döner OK: " + timePassedOverall);
    }
resw67
  • 139
  • 3
  • 6