Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

356
Visualizações
Unity 2D. How to rotate an object smoothly inside a Coroutine?

I'm newbie here, but will try to describe as clear as I can. (it's not that important, just to clarify) So I want to rotate an object for 405deg in 1 second only once, when space is pressed. I've thought it should be done using coroutines, so I've wrote something like this:

private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StopAllCoroutines(); //to prevent overlapping
            StartCoroutine(Rotate());
        }
    }

    IEnumerator Rotate()
    {
        //where final finalRotation is a rotation i want to get in a result
        Quaternion finalRotation = Quaternion.Euler(0, 0, 405) * transform.rotation;
/*
using do..while to make sure that object will rotate even in case it's in same rotation as finalRotation
*/
        do
        {
            //should smoothly rotate an object for 405deg in 1 sec but it doesnt
            transform.Rotate(Vector3.forward, 405f * Time.deltaTime / 1f);
        } while (transform.rotation != finalRotation);
        yield return 1;
    }

The code above works fine and everything is ok except one, it rotates an object instantly and not smoothly. I mean, if I use that line of code in Update, everything go smoothly

transform.Rotate(Vector3.forward, 405f * Time.deltaTime / 1f);

So my questions:

  1. Why does it rotate smoothly in Update, but instantly in the coroutine;

  2. and how can that be fixed?

Thanks in advance, once again, sorry if I made some mistakes when making a topic.

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

It updates instantly in the coroutine because you only yield when the rotation is complete. The frame wont be rendered until every pending/running coroutine yields or completes, so here your rotation completes and then finally the frame is rendered, making it an instant rotation.

Instead, you should yield in the loop.

You should also be aware that Quaternion finalRotation = Quaternion.Euler(0, 0, 405) * transform.rotation; and transform.Rotate(Vector3.forward, 405f); can have different results depending on parent object rotations, because they rotate in different spaces, the first rotating in global and the second rotating in local. This may result in the loop as written actually never ending.

Another problem is that there is no guarantee that summing up Time.deltaTime values will ever add up to 1f. Suppose on the very first frame, lag occurs, causing Time.deltaTime to be huge, 2f. You can see how it might never end as a result. As an alternative, you should remember the start rotation, then on each frame calcuate the rotation from that frame, then apply it that frame.

Altogether:

IEnumerator Rotate()
{
    Quaternion startRotation = transform.rotation;
    float endZRot = 405f;
    float duration = 1f;
    float t = 0;

    while (t < 1f)
    {
        time = Mathf.Min(1f, t + Time.deltaTime/duration);
        Vector3 newEulerOffset = Vector3.forward * (endZRot * t);      
        // global z rotation
        transform.rotation = Quaternion.Euler(newEulerOffset) * startRotation;
        // local z rotation
        // transform.rotation = startRotation * Quaternion.Euler(newEulerOffset);
        yield return null;
    } 
}
over 4 years ago · Santiago Trujillo Relatório

0

yield return null will wait one frame inside a coroutine. Right now you have placed the yield return 1; outside the while loop, so it wont do anything. In this situation I whould lerp between the two rotations in a while loop that goes from 0->1

or (if you dont want to do any of this stuff and dont care for a bit of bloat) use leantween, https://assetstore.unity.com/packages/tools/animation/leantween-3595

over 4 years ago · Santiago Trujillo Relatório

0

In the place where you rotate it one increment you have to wait for some time. Try

yield return new WaitForSeconds(0.1);

Also while I was typing this someone else answered.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda