- Home /
foreach loop problem
public class TEST : MonoBehaviour {
public List<int> numbers = new List<int>() { 1, 2, 3 };
public void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Test();
}
}
public void Test()
{
foreach (int number in numbers)
{
Debug.Log(number);
}
}
}
Currently when I press the spacebar all the numbers appear in the console. What I want to happen is that only one number appear in the console I.e if I press spacebar once then the console says 1, if I press spacebar again then the console says 2 and finally when I press it a third time it says 3.
Answer by AlgoUnity · Sep 23, 2021 at 03:30 AM
public class TEST : MonoBehaviour {
public List<int> numbers = new List<int>() { 1, 2, 3 };
public int nextNumber = 0;
public void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Test();
}
}
public void Test()
{
Debug.Log(numbers[nextNumber]);
nextNumber = (nextNumber + 1) % numbers.Length; //bring nextNumber back to 0 at the end
}
}
*Count not Length But other than that it works perfectly. Thank you!
Actually I was wondering if there's a way to keep the foreach loop?
The game runs at 60 frames per second, Update() is called 60 times per second, and will do everything inside it within that frame. You can't pause the function in the middle and continue on the next update. If you absolutely have to do that, look up Coroutines on google, which are a bit more complicated, but they are not so bad. Definitely a few steps up from what you are doing here though.
While you conceivably *could* maintain the foreach() loop, it would be terribly cumbersome (and, if the List<> were to change contents partway through the loop, potentially less predictable than a regular for() loop alternative).
For proof of concept, here's an example of keeping the foreach() loop, but I can't say I would *ever* recommend its use, because it's needlessly bulky in practice:
public KeyCode triggerKey = KeyCode.Space;
private bool trigger = false;
void Start()
{
StartCoroutine(Test());
}
void Update()
{
if(Input.GetKeyDown(triggerKey))
{
TestTrigger();
}
}
IEnumerator Test()
{
foreach(int number in numbers)
{
// Loop here until triggered, when it will leave the loop
// and repeat on the next foreach() entry
while(!trigger)
{
yield return null;
}
trigger = false;
Debug.Log(number);
}
// Since this script is untested, I forget whether
// it's actually necessary to guarantee a yield on all
// paths of an IEnumerator function, so this is here
// as a safety net
yield return null;
}
void TestTrigger()
{
trigger = true;
}
Right, but instead of using that bool variable you can directly check the input in the coroutine
public KeyCode triggerKey = KeyCode.Space;
void Start()
{
StartCoroutine(Test());
}
IEnumerator Test()
{
foreach(int number in numbers)
{
while(!Input.GetKeyDown(triggerKey))
{
yield return null;
}
Debug.Log(number);
}
}
This actually has the additional benefit once the coroutine has finished, there's no overhead anymore since we don't need the update method at all. Of course if you want to repeat the loop once it ran through, you can wrap the foreach loop in an endless while loop