- Home /
How can I show objects in succession when a button is pressed?
Hello everyone, I am doing a project in which I need to show different renederings of the same object one at a time. My idea was to use a button, so that when the first object is shown, once the button is pressed the object is hidden and once it is pressed again the next object is shown and so on for all the objects. I have written a code, using different for loops, but my problem is that once I press the button in playmode, to hide the first object, all the other objects are skipped and it goes straight to the last object in the array. Can anybody help me and tell me if I am missing something? I will attach the code I wrote. Thanks in advance to anybody willing to help me!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Exp1 : MonoBehaviour
{
public GameObject[] array = new GameObject[14];
// Start is called before the first frame update
void Start()
{
for (int i=1; i<array.Length; i++)
{
array[i].SetActive(false);
}
}
// Update is called once per frame
void Update()
{
Vector3 pos = new Vector3(0,0,0);
for (int i=1; i < array.Length; i++)
{
array[i].transform.position = pos;
}
}
public void whenButtonClicked()
{
for (int i=1; i<array.Length; i++)
{
if (array[i-1].activeInHierarchy == true)
array[i-1].SetActive(false);
else
array[i].SetActive(true);
}
}
}
Answer by jackmw94 · May 23 at 11:11 AM
Let's run through what's happening in your whenButtonClicked
function. Say we have 5 gameobjects in the array and we start with only the first (index=0) gameobject active:
In the first loop i
will equal 1, we will check whether the element at index 0 is on which it is so we turn it off. In the second loop i
will equal 2, we check whether the element at index 1 is on which it isn't so we turn on the element at index 2 - this is because you use i
instead of i - 1
in your else statement. In our third loop i
will equal 3 and we'll check whether the element at index 2 is on which it is since we turn it on in the last iteration and so we turn it off. In the fourth loop i
will equal 4 and we'll check the element at index 4 which is off so we turn it on (the last element). We don't loop a third time since our condition i<array.Length
stops us once i
gets to 5.
There is a fair bit of confusion happening in this for loop but I think the main thing that we want to avoid here is changing a gameobject to active or inactive in one iteration of the loop then checking that recently changed value in the next iteration.
If I were you, I'd keep an integer value within my script stating which index should be active. Your for-loop could then increment this value when clicked then set each gameobject to active only if the index i
equals this value.
int currentActiveObjectIndex = 0;
public void whenButtonClicked()
{
currentActiveObjectIndex++;
UpdateCurrentlyActiveObject();
}
private void UpdateCurrentlyActiveObject()
{
for (int i=0; i<array.Length; i++)
{
array[i].SetActive(i == currentActiveObjectIndex);
}
}
Also note how I've separated the function that updates the visibility - this means that we can call this from wherever and it will always be correct for the currentActiveObjectIndex
.
By structuring the code this way, we have a lot more control over what is being shown. If you wanted a reset button that started at the first picture then all that would have to do is set currentActiveObjectIndex
to 0 then call UpdateCurrentlyActiveObject
. Similarly if you wanted a back button it would only have to decrement currentActiveObjectIndex
before calling the update active object function.
The last consideration I'd add to this would be to ensure that our index is always within the bounds of our array. One way to handle this nicely would be to "Clamp" the value: currentActiveObjectIndex = Mathf.Clamp(0, array.Length-1, currentActiveObjectIndex);
. (https://docs.unity3d.com/ScriptReference/Mathf.Clamp.html)
Great, thank you very much for your clarity! I tried your suggestions and now the code seems to work! Thank you again.
Lovely! Let me know if you have any queries about it. Could you please mark the answer as accepted :)