• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by tmalhassan · Oct 08, 2017 at 07:56 AM · c#unity 5coroutineloop

Coroutine gets stuck randomly?

The question says it all, I have a Coroutine that I am using to create some spinning animation. The problem is that it suddenly stops randomly (at different times). I don't know what might be causing this as it works most of the times (8 times out of 10) on PC. I also built the game and tried it on an android phone but it only works (3 times out of 10). Any idea what might be causing this?

EDIT:

This is my Script:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class SpinWheelScript : MonoBehaviour {
 
     public CanvasGroup spinWheelCanvas;
 
     public GameObject[] rewards;
     public GameObject[] pointerDir;
     public GameObject[] ringDir;
     public GameObject pointer;
     public GameObject ring;
 
     private Quaternion pointerTargetRotation;
     private Quaternion ringTargetRotation;
 
     private bool spinIsEnabled = false;
     private bool isSpinning = false;
     private bool lastSpin = false;
     private bool animationIsEnabled = false;
 
     private float time;
     private float pSpeed;
     private float rSpeed;
     private float pointerRotateFloat;
     private float ringRotateFloat;
 
     private int rewardEnabler = 0;
     private int randomReward;
     private int pRandomDir;
     private int rRandomDir;
     private int plastRandomDir = 0;
     private int rlastRandomDir = 0;
 
     private void Update()
     {
         if (spinIsEnabled == false)
         {
             // Do Nothing
         }
 
         else if (spinIsEnabled == true && isSpinning == false)
         {
             // Select reward
             if (rewardEnabler == 0)
             {
                 RewardSelector();
                 rewardEnabler = 1;
             }
 
             StartCoroutine(Spin());
         }
 
         if (lastSpin == true)
         {
             //randomReward = 4;
             Debug.Log(randomReward);
 
             pointerRotateFloat = ((360 - (randomReward * 60)) - 30);
             ringRotateFloat = ((360 - (randomReward * 60)) - 30);
 
             if (pointerRotateFloat > ringRotateFloat)
             {
                 pSpeed = (pointerRotateFloat);
                 rSpeed = (pointerRotateFloat / ringRotateFloat) * (ringRotateFloat);
             }
             else
             {
                 rSpeed = (ringRotateFloat);
                 pSpeed = (ringRotateFloat / pointerRotateFloat) * (pointerRotateFloat);
             }
 
             Quaternion pointerTargetRotation = Quaternion.Euler(new Vector3(0, 0, pointerRotateFloat));
             pointer.transform.rotation = Quaternion.RotateTowards(pointer.transform.rotation, pointerTargetRotation, pSpeed * Time.deltaTime);
             Quaternion ringTargetRotation = Quaternion.Euler(new Vector3(0, 0, ringRotateFloat));
             ring.transform.rotation = Quaternion.RotateTowards(ring.transform.rotation, ringTargetRotation, rSpeed * Time.deltaTime);
 
             if ((pointer.transform.rotation == pointerTargetRotation) && (ring.transform.rotation == ringTargetRotation))
             {
                 lastSpin = false;
                 isSpinning = false;
                 spinIsEnabled = false;
                 animationIsEnabled = true;
             }
         }
     }
 
     IEnumerator Spin()
     {
         isSpinning = true;
         pSpeed = 0;
         rSpeed = 0;
         time = 0;
 
         while (time < 15)
         {
             pRandomDir = PointerRandomDirection();    // Function to pick a random number.
             rRandomDir = RingRandomDirection();    // Function to pick a random number.
 
             for (;;)
             {
                 pointerRotateFloat = (((pRandomDir + 1) * 60) - 30) - pointer.transform.rotation.z;
                 ringRotateFloat = (((rRandomDir + 1) * 60) - 30) - ring.transform.rotation.z;
 
                 if (pointerRotateFloat > ringRotateFloat)
                 {
                     pSpeed = (pointerRotateFloat);
                     rSpeed = (pointerRotateFloat / ringRotateFloat) * (ringRotateFloat);
                 }
                 else
                 {
                     rSpeed = (ringRotateFloat);
                     pSpeed = (ringRotateFloat / pointerRotateFloat) * (pointerRotateFloat);
                 }
 
                 pointerTargetRotation = Quaternion.Euler(new Vector3(0, 0, pointerRotateFloat));
                 pointer.transform.rotation = Quaternion.RotateTowards(pointer.transform.rotation, pointerTargetRotation, pSpeed * Time.deltaTime);
                 ringTargetRotation = Quaternion.Euler(new Vector3(0, 0, ringRotateFloat));
                 ring.transform.rotation = Quaternion.RotateTowards(ring.transform.rotation, ringTargetRotation, rSpeed * Time.deltaTime);
 
                 if ((pointer.transform.rotation == pointerTargetRotation) && (ring.transform.rotation == ringTargetRotation))
                     break;
 
                 yield return null;
             }
 
             time++;
         }
 
         lastSpin = true;
     }
 
     private int RewardSelector()
     {
         randomReward = Random.Range(0, rewards.Length);
 
         return randomReward;
     }
 
     private int PointerRandomDirection()
     {
         int pRandomDir = plastRandomDir;
 
         if (pointerDir.Length <= 1)
             return 0;
 
         while (pRandomDir == plastRandomDir)
         {
             pRandomDir = Random.Range(0, pointerDir.Length);
         }
 
         plastRandomDir = pRandomDir;
         return pRandomDir;
     }
 
     private int RingRandomDirection()
     {
         int rRandomDir = rlastRandomDir;
 
         if (ringDir.Length <= 1)
             return 0;
 
         while (rRandomDir == rlastRandomDir)
         {
             rRandomDir = Random.Range(0, ringDir.Length);
         }
 
         rlastRandomDir = rRandomDir;
         return rRandomDir;
     }
 
     public void OnSpinButtonClick()
     {
         if(spinIsEnabled == false && isSpinning == false)
             spinIsEnabled = true;
 
         spinWheelCanvas.interactable = false;
     }
 }

Thanks in advance.

Comment
Add comment · Show 7
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image PizzaPie · Oct 08, 2017 at 01:08 PM 1
Share

Do you call it multiple times? meaning, it is running and you call it again.

avatar image Bunny83 PizzaPie · Oct 08, 2017 at 01:19 PM 0
Share

Yep, that's the most likely cause. With different target rotation each, none of them can ever finish as they work against each other.

avatar image tmalhassan Bunny83 · Oct 08, 2017 at 02:39 PM 0
Share

@PizzaPie yeah I am sure I am only calling it once. Elsewise, why would it work most of the times and some other times it wouldn't?

Show more comments
Show more comments
avatar image tmalhassan · Oct 08, 2017 at 08:56 PM 0
Share

@PizzaPie @Bunny83 @yanivng I just updated my question with the entire script. I was actually avoiding doing that because the script is quite messy. I tried cleaning it up as much as possible. Thank you.

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by FortisVenaliter · Oct 09, 2017 at 07:14 PM

I'd say it's probably line 123 in your example code.

You have for(;;) which is an infinite loop when it doesn't have a break.

You do have a break statement in there, but it only executes if two quaternions are exactly equal. With floating point precision issues, it doesn't surprise me that you end up with indeterminate behaviour.

The problem is that it's likely bouncing back and forth between -0.000000001 and 0.0000000001, never actually hitting that match you're looking for and keeping the infinite loop running.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Oct 09, 2017 at 08:21 PM 3
Share

No, both concerns you mentioned do not really apply. The for-loop is an intentional infinite loop. He has an unconditional yield return null; at the end of the for loop, so no problem here. The loop does one iteration every frame.

RotateTowards is implemented like this:

 public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta)
 {
     float num = Quaternion.Angle(from, to);
     Quaternion result;
     if (num == 0f)
     {
         result = to;
     }
     else
     {
         float t = $$anonymous$$athf.$$anonymous$$in(1f, maxDegreesDelta / num);
         result = Quaternion.SlerpUnclamped(from, to, t);
     }
     return result;
 }

The == operator of the quaternion struct looks like this:

 public static bool operator ==(Quaternion lhs, Quaternion rhs)
 {
     return Quaternion.Dot(lhs, rhs) > 0.999999f;
 }

So as soon as the remaining delta becomes smaller than the "maxDegreesDelta" the t value is clamped to "1" so it will return "to" so the break condition should work fine.

Of course the computation of the target angle makes no sense as he subtracts one of the quaternion components from an angle in degree. However the effect is neglectable since we deal with unit quaternions so he just subtracts a value between -1 and 1. The overall logic how he rotates the object seems to be overcomplicated. It's hard to actually tell what the intention is, especially since the calculation of the angle makes not much sense.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

435 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Executing coroutines consecutively 0 Answers

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

Animation method/coroutine playable once or loop 0 Answers

Coroutine For Loop Will Not End 1 Answer

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges