Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

C# Rotation Not Working Properly

Discussion in 'Scripting' started by kittik, Apr 30, 2015.

  1. kittik

    kittik

    Joined:
    Mar 6, 2015
    Posts:
    565
    Hi, I am trying to rotate a 2D object one way, then another in a continuous loop.

    Code (CSharp):
    1. public class GearChangeSpin : MonoBehaviour {
    2.     void Update() {
    3.         StartCoroutine (spin());
    4.     }
    5.  
    6.     IEnumerator spin() {
    7.         transform.Rotate(0, 0, -0.5f);
    8.         yield return new WaitForSeconds(1.5f);
    9.         StartCoroutine (spinOtherWay());
    10.     }
    11.  
    12.     IEnumerator spinOtherWay() {
    13.         transform.Rotate(0, 0, 0.5f);
    14.         yield return new WaitForSeconds (1.5f);
    15.         StartCoroutine (spin());
    16.     }
    17. }
    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
     
    Last edited: Apr 30, 2015
  2. hamsterbytedev

    hamsterbytedev

    Joined:
    Dec 9, 2014
    Posts:
    353
    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.
     
  3. Zerot

    Zerot

    Joined:
    Jul 13, 2011
    Posts:
    135
    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.
     
    hamsterbytedev likes this.
  4. hamsterbytedev

    hamsterbytedev

    Joined:
    Dec 9, 2014
    Posts:
    353
    I also noticed that. You definitely don't want to start your coroutine in the update method.
     
  5. kittik

    kittik

    Joined:
    Mar 6, 2015
    Posts:
    565
    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!
     
    hamsterbytedev likes this.
  6. hamsterbytedev

    hamsterbytedev

    Joined:
    Dec 9, 2014
    Posts:
    353
    Code (CSharp):
    1. if(wobbleSpeed != 0 && alwaysWobble ){
    2.             _rotationTimer += Time.deltaTime;
    3.             float phase = Mathf.Sin(_rotationTimer / (1 / wobbleSpeed));
    4.             transform.localRotation = Quaternion.Euler( new Vector3(0, 0,  phase * wobbleAngle));
    5.         }
    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.
     
  7. Zerot

    Zerot

    Joined:
    Jul 13, 2011
    Posts:
    135
    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:
    Code (csharp):
    1.  
    2. while(enabled)
    3. {
    4.     rotSpeed = 0.5f;
    5.     yield return new WaitForSeconds(1.5f);
    6.     rotSpeed = -0.5f;
    7.     yield return new WaitForSeconds(1.5f);
    8. }
    9.  
     
    hamsterbytedev likes this.
  8. hamsterbytedev

    hamsterbytedev

    Joined:
    Dec 9, 2014
    Posts:
    353
    This would also work. Sine waves are just how I would do it. There's more than one way to skin a cat.
     
  9. kittik

    kittik

    Joined:
    Mar 6, 2015
    Posts:
    565
    Hey, I am trying to implement the code and am having trouble.
    Code (CSharp):
    1.  
    2. public class GearChangeSpin : MonoBehaviour {
    3.  
    4.     public float rotSpeed;
    5.  
    6.     void Update() {
    7.         //StartCoroutine (spin());
    8.         transform.Rotate(0, 0, rotSpeed);
    9.         StartCoroutine (spin());
    10.     }
    11.  
    12.     IEnumerator spin() {
    13.         while (enabled) {
    14.             rotSpeed = 0.5f;
    15.             yield return new WaitForSeconds (1.5f);
    16.             rotSpeed = -0.5f;
    17.             yield return new WaitForSeconds (1.5f);
    18.         }
    19.     }
    20.  
    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.
     
    Last edited: Apr 30, 2015
  10. kittik

    kittik

    Joined:
    Mar 6, 2015
    Posts:
    565
    Code (CSharp):
    1. public class GearChangeSpin : MonoBehaviour {
    2.  
    3.     public float rotSpeed;
    4.     private bool isTurning;
    5.  
    6.     void Update() {
    7.         transform.Rotate(0, 0, rotSpeed);
    8.         StartCoroutine (spin());
    9.     }
    10.  
    11.     IEnumerator spin() {
    12.         while (isTurning == false) {
    13.             rotSpeed = 0.5f;
    14.             yield return new WaitForSeconds (1.5f);
    15.             isTurning = true;
    16.         }
    17.         while (isTurning == true) {
    18.             rotSpeed = -0.5f;
    19.             yield return new WaitForSeconds (1.5f);
    20.             isTurning = false;
    21.         }
    22.     }
    It all works now! Thanks for the help.
     
  11. Zerot

    Zerot

    Joined:
    Jul 13, 2011
    Posts:
    135
    ... 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!