- Home /
When object i in Array is enabled, all other objects in Array are disabled.
I have an interesting problem that I'm probably overthinking, so I could use a fresh perspective. My game has a journal, each "page" of the journal is a GUIText with info about a different animal (on this level, it's 3 pages). When you press "open journal", it creates the "Prev" and "Next" buttons to flip through the journal.
All GUIText components are disabled initially. When you open the journal and press Next, it sets page 0 to "enabled" and increments i++ so the next time you click Next, page 1 is enabled. I tried to add "disable i-1" but since 0-1 = -1 it says Error: Index out of Range the first time I click.
Essentially, I need PageOn() to say "when object i is enabled, all other objects in the array are disabled", so you can only read one page at a time without text overlapping each other. I need this to be reusable for an array of any size, because the journal will have different numbers of pages on each level. And eventually, I want the reverse to happen when you press the "Prev" button. Thanks in advance for any help.
var subMenu : boolean = false;
var aAnimals : GUIText[];
private var i : int = 0;
function Start()
{
//turn prev and next buttons off initially
subMenu = false;
i = 0;
}
function OnGUI()
{
if(!subMenu)
{
if(GUI.Button(Rect(10,10,100,50), "Open Journal"))
{
subMenu = true;
Debug.Log("opened journal");
}
}
else if(subMenu)
{
//when journal opened, create prev and next buttons
if(GUI.Button(Rect(10,75,50,50), "Prev"))
{
//Go to previous page
}
if(GUI.Button(Rect(75,75,50,50), "Next"))
{
//Go to next page
PageOn();
}
//changes Open Journal to say Close Journal
if(GUI.Button(new Rect(10,10,100,50), "Close Journal"))
{
Debug.Log("closed journal");
//turns off prev and next buttons
subMenu = false;
}
}
}
function PageOn()
{
//turn on page 0
aAnimals[i].enabled = true;
//increment i for the next time the "Next" button is pressed
i++;
//wrapper to prevent "index out of range" error when you reach the end
i = i % aAnimals.Length;
}
To make a cycling counter (both positive and negative) use:
i = (i + Count) % Count; // here Count is aAnimals.Length
While that is an optimization, and there's nothing wrong with that, I'm a bit concerned about writing statements like that. For instance, say that the gui element is a 'book'. If going to the next page and going back a page 'flips the page on the book' with an animation, you definitely make it harder on yourself if you combine both types of operations.
Answer by astorga · Dec 11, 2012 at 04:41 PM
You just need to do some checks to make these operations:
First of all, make sure the "Previous" button doesn't appear when you are on first page (same check for last page and "Next" button).
Every time you advance a page, enable the next/previous one and then disable the current one (if you won't animate it, the order doesn't matter that much. Just make sure there's always a page to show). Like here:
function OnGUI(){
//...
//check if we can go back one page
if(i > 0){
if(GUI.Button(Rect(10,75,50,50), "Prev"))
{
//Go to previous page
PrevPage();
}
}
//check if we can advance a page
if(i < (aAnimals.Length - 1)){
if(GUI.Button(Rect(75,75,50,50), "Next"))
{
//Go to next page
NextPage();
}
}
}
function NextPage(){
aAnimals[i+1].enabled = true;
aAnimals[i].enabled = false;
i++;
}
function PrevPage(){
aAnimals[i-1].enabled = true;
aAnimals[i].enabled = false;
i--;
}
It will work as long as you "open the book" with only one page enabled. Is it what you need?
EDIT: Added the correct code.
That worked nicely, thank you. I had to add a little to your code, like i-- for PrevPage. Also, I added some code to show page 1 when Open Journal is called, and to disable all pages when Close Journal is called. Overall it works.
I still have one error message though, when I click Next Page on the last page, I still get "Array index is out of range", even though I have the % wrapper, it doesn't seem to work. Here's the current code:
function Start()
{
sub$$anonymous$$enu = false;
i = 0;
}
function OnGUI()
{
if(!sub$$anonymous$$enu)
{
if(GUI.Button(Rect(10,10,100,50), "Open Journal"))
{
sub$$anonymous$$enu = true;
Debug.Log("opened journal");
//show page 1 when opened
aAnimals[i].enabled = true;
}
}
else if(sub$$anonymous$$enu)
{
//check if we can go back one page
if(i > 0)
{
if(GUI.Button(Rect(10,75,50,50), "Prev"))
{
//Go to previous page
PrevPage();
Debug.Log("prev page");
}
}
//check if we can advance a page
if(i < aAnimals.Length - 1)
{
if(GUI.Button(Rect(75,75,50,50), "Next"))
{
//Go to next page
NextPage();
Debug.Log("next page");
}
}
if(GUI.Button(new Rect(10,10,100,50), "Close Journal"))
{
Debug.Log("closed journal");
sub$$anonymous$$enu = false;
//disable all pages in array when closed
for(var i in aAnimals)
{
i.enabled = false;
Debug.Log("disabled");
}
//reset i so page 1 shows first next time
i = 0;
}
}
}
function NextPage()
{
aAnimals[i+1].enabled = true;
aAnimals[i].enabled = false;
i++;
}
function PrevPage()
{
aAnimals[i-1].enabled = true;
aAnimals[i].enabled = false;
i--;
}
Ah, my bad, sorry. The array length is 1 unit bigger than the last index. I fixed that in my answer. Take a look now.
That's perfect, thanks for the quick and helpful response! It turns out the wrapper is not needed anymore in NextPage() and PrevPage() so I'll edit the code to take those out.
Answer by FlowStateGames · Dec 11, 2012 at 06:19 PM
Okay, so really, you are kinda overthinking this. If your initial state is that none of them are enabled, then you really only want this:
int currentPage = 0;
void NextPage()
{
// no matter the current page, we know that we disable
journal[currentPage].enabled = false;
// always start with the "bad case"
if(currentPage == journal.Length - 1)
{
// let's loop to the first page
currentPage = 0;
}
else
{
currentPage++;
}
EnablePage();
}
void PrevPage()
{
// no matter the current page, we know that we disable
journal[currentPage].enabled = false;
// again, start with the 'bad case'
if(currentPage == 0)
{
// go to the last page
currentPage = journal.Length - 1;
}
else
{
currentPage--;
}
EnablePage();
}
void EnablePage()
{
journal[currentPage].enabled = true;
}
Now, it may look silly that I built 3 separate methods for something so trivial. But there's a reason. You could have different animations for going to a previous page, or a next page. More to the point, there could be some checks you do when you enable the page.
If you don't separate these methods, you run the real risk of creating obfuscated code when you go to add functionality. Plus, it's easier to read.