C# Rotation Not Working Properly

Hi, I am trying to rotate a 2D object one way, then another in a continuous loop.

public class GearChangeSpin : MonoBehaviour {
    void Update() {
        StartCoroutine (spin());
    }

    IEnumerator spin() {
        transform.Rotate(0, 0, -0.5f);
        yield return new WaitForSeconds(1.5f);
        StartCoroutine (spinOtherWay());
    }

    IEnumerator spinOtherWay() {
        transform.Rotate(0, 0, 0.5f);
        yield return new WaitForSeconds (1.5f);
        StartCoroutine (spin());
    }
}

What happens when I start the scene is that for 1.5 seconds my sprite will rotate the correct way, then after calling spinOtherWay() it tries to do both spin() and spinOtherWay() at once - jamming the movement.

Is there a way to completely halt spin() and spinOtherWay() as I do not want their functions to continue until otherwise stated? Does the problem stem from using void Update() to start off the process? I tried change void Update() to void Start() and there was no movement whatsoever.

Thanks,

Kittik

Have you ever heard of sine waves? I used a sine wave to make a wobbling platform that basically rotated so far one way, then the same in the other direction in a continuous loop. I can dig up the script if it would help. It’s much shorter than what you are doing. I think it was only a few lines.

The problem is not your rotate, it is your use of coroutines. You are starting a coroutine every update and again in every coroutine. meaning that after a few seconds you will have hundreds of coroutines running(60fps*10sec == 600 update calls).

You will only want to start to coroutine once. In Start for example. You will also need a few loops in your coroutines for it to work as you want.

1 Like

I also noticed that. You definitely don’t want to start your coroutine in the update method.

I have not heard of sine waves. Any further help would be much appreciated. Yes, I too know of the issue of having loads of update calls, I was making it this way simply because I didn’t know how to otherwise. Will look up sine waves now!

1 Like
if(wobbleSpeed != 0 && alwaysWobble ){
            _rotationTimer += Time.deltaTime;
            float phase = Mathf.Sin(_rotationTimer / (1 / wobbleSpeed));
            transform.localRotation = Quaternion.Euler( new Vector3(0, 0,  phase * wobbleAngle));
        }

Just modify the variables to suit your needs. You’ll want a float to store the timer. A float to store the angle in degrees, and a float to store the speed at which to rotate. Oh, and just run it in the normal update and attach the script to the object you wish to rotate.

you don’t need sine waves for this. You just need to fix your coroutines.

What you can do is this: apply rotation in Update and set the rotation direction in a coroutine. Then the coroutine code would just be:

while(enabled)
{
    rotSpeed = 0.5f;
    yield return new WaitForSeconds(1.5f);
    rotSpeed = -0.5f;
    yield return new WaitForSeconds(1.5f);
}
1 Like

This would also work. Sine waves are just how I would do it. There’s more than one way to skin a cat.

Hey, I am trying to implement the code and am having trouble.

public class GearChangeSpin : MonoBehaviour {

    public float rotSpeed;

    void Update() {
        //StartCoroutine (spin());
        transform.Rotate(0, 0, rotSpeed);
        StartCoroutine (spin());
    }

    IEnumerator spin() {
        while (enabled) {
            rotSpeed = 0.5f;
            yield return new WaitForSeconds (1.5f);
            rotSpeed = -0.5f;
            yield return new WaitForSeconds (1.5f);
        }
    }

What am I doing that is causing a problem? Should I have declared an arbitrary float in the constructor or something? Thanks for the help thus far.

public class GearChangeSpin : MonoBehaviour {

    public float rotSpeed;
    private bool isTurning;

    void Update() {
        transform.Rotate(0, 0, rotSpeed);
        StartCoroutine (spin());
    }

    IEnumerator spin() {
        while (isTurning == false) {
            rotSpeed = 0.5f;
            yield return new WaitForSeconds (1.5f);
            isTurning = true;
        }
        while (isTurning == true) {
            rotSpeed = -0.5f;
            yield return new WaitForSeconds (1.5f);
            isTurning = false;
        }
    }

It all works now! Thanks for the help.

… You are still starting your coroutine in update. Update is called every frame(so at 60fps 60 times a second). Meaning that you will start extra coroutines 60 times a second. meaning that after a short while it will get very very slow because you will have 1000s of coroutines running. You need to start it only once!