- Home /
Coroutine While loop help
I have a coroutine with a while loop that I'd like to keep repeating for a couple seconds until a condition is met but it isn't looping through multiple times so I cant make a gun look at another object using slerp. What is causing the while loop to be run one time then shut off? What is the best way to make a while loop run until a condition is met? Would a bool be the best way or no? The code below is suppose to run for a couple seconds then by the time the waitforseconds is done the gun should be done moving. Is this the best way to do this? Thanks for the info
public IEnumerator LookAt1()
{
LookAt = true;
while (LookAt == true) {
//Body
Quaternion Rot1 = Quaternion.LookRotation (RM.Priority1Plastic [0].transform.FindChild ("LookAt1").position - this.gameObject.transform.position);
this.gameObject.transform.rotation = Quaternion.Slerp (this.gameObject.transform.rotation, Rot1, Time.deltaTime * 3);
//Gun
Quaternion Rot = Quaternion.LookRotation (RM.Priority1Plastic [0].transform.FindChild ("LookAt1").position - Gun.transform.position);
Gun.transform.rotation = Quaternion.Slerp (Gun.transform.rotation, Rot, Time.deltaTime * 3);
}
yield return new WaitForSeconds (3);
LookAt = false;
}
Answer by Le-Clam-Burglar · Dec 09, 2016 at 04:50 AM
If you want the code in your Coroutine to run for 3 seconds then this should do the trick:
public IEnumerator LookAt1()
{
float duration = Time.time + 3.0f;
while (Time.time<duration)
{
// Put your code in here
yield return null;
}
}
Hope this helps out, be sure to let me know if you need any additional help, this is my first time answering here! (b")b
So my code would run and it would go through the while loop and ignore the yield return null until it reached the amount of time?
yield return null; makes the coroutine resume after the next Update.
If you want to call the coroutine without the risk of having multiple coroutines running in parallel you could add this.
using System.Collections;
using UnityEngine;
public class Coroutines : $$anonymous$$onoBehaviour
{
Coroutine LookAtCoroutine;
public void StartLookAt()
{
if (LookAtCoroutine != null)
{
StopCoroutine(LookAtCoroutine);
}
LookAtCoroutine = StartCoroutine(LookAt());
}
IEnumerator LookAt()
{
var duration = Time.time + 3.0f;
while (duration > Time.time)
{
//Do stuff here
yield return null;
}
}
}
Then you just call StartLookAt() whenever you want.
Answer by RobAnthem · Dec 09, 2016 at 08:47 PM
Adding a return of any kind will immediately terminate the rest of the code.
Then how would I run my code then shut it off later on?
bool loopBool = true;
while (loopBool)
{
//do stuff
//once parameters are satisified
if (parameter y == x)
loopBool = false;
}
Would the yield return null go inside the while loop or outside of it?
Well if it is irregardless to the While loop, then I'd suggest putting it in the section that closes the While loop, so you get your return, the loop ends, and it can be started back up any time you trigger the bool true again. For a continuous loop, I'd put the loopBool = true inside the Update, but be careful about using While loops in Update scripts, it can get resource heavy very quickly.
Rob, you should lookup C# iterators or Unity coroutines because it looks like you don't really understand them.
The yield statement will turn the method into a statemachine class. yield return
does not ter$$anonymous$$ate a coroutine but suspends it at this point. Unity uses C# interator blocks to implement coroutines.
Have a look at this pure C# example:
IEnumerable $$anonymous$$yIterator(int aValue)
{
yield return 1;
yield return aValue*2;
yield return 42;
}
This is also an iterator method but ins$$anonymous$$d of IEnumerator i used IEnumerable. That way it can be used in a foreach loop like this:
foreach(int val in $$anonymous$$yIterator(5))
{
Debug.Log("Value: " + val);
}
This example will print 3 logs:
"Value: 1"
"Value: 10"
"Value: 42"
It's the same as doing:
IEnumerable myEnumerable = $$anonymous$$yIterator(5); // create the "statemachine wrapper"
IEnumerator enumerator = myEnumerable.GetEnumerator(); // create an actual implementation of the statemachine
while (enumerator.$$anonymous$$oveNext()) // move to next yield statement
{
Debug.Log("Value: " + (int)enumerator.Current);
}
$$anonymous$$oveNext will iterate through the statemachine and Current will hold the value that the last yield statement "returned". $$anonymous$$oveNext will return true as long as the iterator is not finised yet. Once an iterator has finished (by reaching the end of the original method or by hitting a yield break;
statement) $$anonymous$$oveNext will return false.
Unity uses this awesome feature of C# to implement coroutines. The coroutine scheduler will care about calling $$anonymous$$oveNext, that's why you have to pass the statemachine object to StartCoroutine. The scheduler uses the returned value to deter$$anonymous$$e when it should resume the coroutine. When you yield "null" the scheduler simply continues your method the next frame. If it's a WaitForSeconds instance it will resume it after the specified amount of time.
Your answer
Follow this Question
Related Questions
Coroutine with Quaternion.Angle 1 Answer
Stop Current Coroutine, Then Restart It 1 Answer
Slerp Finishes Rotation When Progress is 0.5f 1 Answer
How to wait for Coroutine to finish? 2 Answers