- Home /
c# Using an IEnumerator yield WaitForSeconds to temporarily pause a While loop
So - I see there are numerous questions relating to this issue, but I've been unable to find one that scratches this particular itch... or if I have, I'm not savvy enough to recognise it. Please be patient - and if you know of a previously answered question that can clear my problem up, please send it right along. =)
I'm executing a while loop which iterates through an array - but as this naturally crashes Unity, I'm trying to execute a coroutine which will slow the execution to once every 4 seconds (in this case).
In theory: The While loop starts, performs the actions in the For section, encounters StartCoroutine(WaitASec (4.0F)); , bounds off to IEnumerator WaitASec, pauses for 4 seconds, then evaluates the While condition and starts again as long as loophandle is true.
In practice: CRASH.
Using Debug.Logs and inserting the line 'loophandle = false' at the end of the While loop seems to indicate that the program reaches the Debug.Log line 'At end of While Loop' BEFORE the Debug.Log line 'Waited a sec'.
So - the newbie is baffled.
Right, code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class CameraControllerRevCsharp : MonoBehaviour {
...
//Boolean switch to turn the tracking on and off
public bool loophandle = true;
...
public void Start() {
Transform target = GameObject.Find("Player").transform;
while (loophandle){
Debug.Log ("Started While Loop");
if(cameraNodes.Count > 0){
int node = 0;
for (int i = 0; i < cameraNodes.Count; i++){
Debug.Log ("Started for section");
if(cameraNodes[i].range >= Vector3.Distance(target.position, cameraNodes[i].position))
{
node = i;
}
}
Debug.Log ("About to transform camera");
transform.position = ( (CameraNode)cameraNodes[node]).position;
}
Debug.Log ("Calling StartCoroutine");
StartCoroutine(WaitASec(4.0F));
// FOR TESTING: loophandle = false;
Debug.Log ("At end of While Loop");
}
}
IEnumerator WaitASec(float waitTime){
yield return new WaitForSeconds(waitTime);
Debug.Log ("Waited a sec");
}
public void Update (){
transform.LookAt(target);
Debug.Log ("Looking at target");
}
}
Thanks for your brain time on this. Here's hoping you can phrase the solution in plain enough language so I never end up doing this bloody stupid thing again. =)
--Rev
Answer by by0log1c · Apr 04, 2012 at 01:47 AM
Hey there again, I just realized the error while going over the comments on the last question. A while loop need to yield a pause every now and then or it'll crash the game.
You may do it like this:
while(true)
{
DoSomething();
yield return null; //wait for a frame
yield return new WaitForSeconds(3.14f);
}
EDIT: I notice you actually call a coroutine that does the waiting, that could work but you need to wait for that method to return after itself waited after the yield to return ;)
You'd do something like:
//method return type has to be IEnumerator
IEnumerator Start()
{
yield return StartCoroutine(MyDelayMethod(3.1415f));
//3.1415 seconds later
}
IEnumerator MyDelayMethod(float delay)
{
yield return new WaitForSeconds(delay);
}
Again, excellent answer! $$anonymous$$uch obliged - I've cleared the old errors from my console and this script is working just fine.
Naturally, I have a new problem now, related to cs0176... and after a couple of hours trying to solve the issue, it turns out that I can't find an answer on this site.
Assu$$anonymous$$g that it's better to be productive than spin my wheels, I'm going to submit another question and get back to work on Blender. =)
Thanks muchly for your time!
(I'll just cough leave this here... http://answers.unity3d.com/questions/235285/cs0176-trying-to-locate-the-main-camera-in-order-t.html )
Still relevant today - you need to use a yield return null in conjunction with the yield return new WaitForXXX.
Apparently using just yield return new WaitForXXX variants fails to process. After much debugging the phantom yield return null was the secret here.
Great catch!
Answer by josetgg · Nov 07, 2012 at 11:16 PM
Just curious, why are you running a while loop on the start function?
Answer by Berenger · Apr 04, 2012 at 02:26 AM
Indeed, calling a coroutine without yielding it's return value in a while() is just going to start a bazillion (and that's a lot !) instances of coroutines and freeze the program.
You would suggest it's better to keep the number of coroutines under a gahzillion, then?
Thanks for the explanatory note - believe me, I need the support (just starting C#).
Answer by VillainT_ · Nov 27, 2012 at 02:47 PM
You can use (for javascript)
while (condition) {
//codes
yield WaitForSeconds (0);
}