I’ve been trying to have an array loop the following way: Start at index 0, go until the end of the array and turning off the previous Game Object while turning on the current, and then looping back around through the array. Currently, my code will run fully through only once and then it alternates between the second index and the third (middle and last in an array of size 3). Here is my code:
public GameObject[] objs;
private int current;
private float timeSinceLastTurn;
void Start() {
//this works
foreach (GameObject i in objs)
{
i.SetActive(false);
}
current = 0;
timeSinceLastTurn = 0.0f;
objs[current].SetActive(true);
}
void Update() {
timeSinceLastTurn += Time.deltaTime;
if (timeSinceLastTurn >= 5.0f)
{
if (current >= objs.Length - 1)
{
objs[current].SetActive(false);
current = 0;
}
else
{
objs[current].SetActive(false);
current += 1;
objs[current].SetActive(true);
timeSinceLastTurn = 0.0f;
}
if (current >= objs.Length - 1)
{
objs[current].SetActive(false);
current = 0;
objs[current].SetActive(true);
timeSinceLastTurn = 0.0f;
}
Putting this on line 20 instead of the current if statement should work. The problem is that youre setting the current Index to 0 put dont set the objs to active.
I know it’s already answered, but I wanted to point out a simpler and easier to follow solution.
void Update()
{
timeSinceLastTurn += Time.deltaTime;
if (timeSinceLastTurn >= 5.0f)
{
objs[current].SetActive(false);
current++;
if (current >= objs.Length)
current = 0;
objs[current].SetActive(true);
timeSinceLastTurn = 0.0f;
}
// [ ... ]
As you can see once we get a time out we deactivate the current one, no matter what value “current” has. Next we just “blindly” increment curremt by 1. Next we check if current is larger than the max allowed index. If it is we wrap around back to 0. After that if statement we are guaranteed to have a valid index for our new object. So in the next step we can just activate the new object and reset the timer.
There’s an even more compact way, though it might be less readable:
if (timeSinceLastTurn >= 5.0f)
{
objs[current++].SetActive(false);
current %= objs.Length;
objs[current].SetActive(true);
timeSinceLastTurn = 0.0f;
}
When we use the post-increment operator we actually get back the value before we increment the variable. (That’s why it’s called post-increment since it increments the value after it was read.).
Of course after inrementing the number it could be out of bounds, however we simply use the modulo operator This ensures current is always in the range 0 to length-1. It it’s larger than that it wraps back to 0.
Just in case you are not familiar with the modulo operator, here’s a quick reminder: An integer division always drops the remainder. So 7 / 3 is just 2. The modulo operator does not return the quotient of the division but the remainder. So 7 % 3 will return a value of 1. Since 2*3 is 6 we have a remainder of 1. When you divide any number smaller than the divisor you get 0. For example 5 / 12 returns 0. The remainder on the other hand will just return the number unchanged. So 5 divided by 12 is 0 and the remainder is 5. This works up to a value of 11. As soon as the value turns 12 we get 12/12 which is 1 with a remainder of 0.
So when we use the modulo operator on an index and “divide” by the element count we get a valid index. Of course the x %= y operator is just the short hand for x = x % y.