0

I'm making a menu for an Android 2d app, I have a bunch of UI panels in multiple menu's and when I press the next right or previous left button the script should set the next panel active and deactive the previous panel, I've tried doing this with a public class with gameobjects but that didn't work and thought a list should work.

In the Unity editor I've set the size to 4 and dragged 4 panels into the script and I'm getting this error:

ArgumentOutOfRangeException: Argument is out of range. Parameter name: index

Here is the relevant part of the script:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MenuControl : MonoBehaviour
{
    //Buttons
    public GameObject ShipUpgradeRight;
    public GameObject ShipUpgradeLeft;

    //Ships
    private int shipUpgradeSelected = 0;
    List<GameObject> ShipList = new List<GameObject>();

    public void Keyword (string keyword)
    {
        if (keyword == "ShipUpgradeLeft") {
            shipUpgradeSelected--;
            ShipList[shipUpgradeSelected].SetActive (true);
            ShipList[shipUpgradeSelected+1].SetActive (false);
        }

        if (keyword == "ShipUpgradeRight") {
            shipUpgradeSelected--;
            CheckShip ();
            ShipList[shipUpgradeSelected].SetActive (true);
            ShipList[shipUpgradeSelected-1].SetActive (false);
        }   
    }
}
CodeSmile
  • 64,284
  • 20
  • 132
  • 217
Dane Gillis
  • 137
  • 1
  • 3
  • 14
  • Firstly, I don't see you populating the List anywhere... Secondly, I don't see you try to clamp the values. Like this there's a chance you could try to access an item at index that doesn't exist.. Try to go through the debugging process and you'll easily see what I mean by that... – walther Jan 31 '15 at 15:54
  • Walther, with populating do you mean i should use ShipList.Add? but in the unity editor i've set the size to 4 and i got 4 elements which i assigned the gameobjects to – Dane Gillis Jan 31 '15 at 16:07
  • If you have it populated by the editor, it's ok, but you should definitely try to go through various states and see what indexes are you trying to access in your method. Especially border values. That's what is causing your problems :) – walther Jan 31 '15 at 16:11

2 Answers2

2

Based on your comments and the actual question I see one possible problem.

The value of shipUpgradeSelected never gets increased. Moreover, shipUpgradeSelected has zero as initial value.

public void Keyword (string keyword)
{
    if (keyword == "ShipUpgradeLeft") {
        shipUpgradeSelected--;
        ShipList[shipUpgradeSelected].SetActive (true);
        ShipList[shipUpgradeSelected+1].SetActive (false);
    }

    if (keyword == "ShipUpgradeRight") {
        shipUpgradeSelected--;
        CheckShip ();
        ShipList[shipUpgradeSelected].SetActive (true);
        ShipList[shipUpgradeSelected-1].SetActive (false);
    }   
}

When keyword equals to ShipUpgradeRight or ShipUpgradeLeft the value of shipUpgradeSelected is decreased (so it's less than zero). And then you try to access the item of list at index that is less than zero.

But this is first problem.

Also you don't clamp (or don't cycle) value of shipUpgradeSelected. So for example you have

if (keyword == "ShipUpgradeRight") {
    shipUpgradeSelected++;
    CheckShip ();
    ShipList[shipUpgradeSelected].SetActive (true);
    ShipList[shipUpgradeSelected-1].SetActive (false);
}

If call Keyword("ShipUpgradeRight"); five times (for example), the value of shipUpgradeSelected is 5. And again it's out of range. So you need to decide how to clamp value of this variable.

d12frosted
  • 1,280
  • 12
  • 33
0

This code works perfect:

public void Keyword(string keyword) {
         if (keyword == "ShipUpgradeLeft") {
             shipUpgradeSelected--;
             if (shipUpgradeSelected < 0) {
                 shipUpgradeSelected = 0;
                 return;
             }

             ShipList[shipUpgradeSelected].SetActive(true);
             if (shipUpgradeSelected + 1 < ShipList.Count) ShipList[shipUpgradeSelected + 1].SetActive(false);
             else ShipList[0].SetActive(false);
         }
         if (keyword == "ShipUpgradeRight") {
             shipUpgradeSelected++;
             if (shipUpgradeSelected >= ShipList.Count) {
                 shipUpgradeSelected = ShipList.Count - 1;
                 return;
             }

             ShipList[shipUpgradeSelected].SetActive(true);
             if (shipUpgradeSelected > 0) ShipList[shipUpgradeSelected - 1].SetActive(false);
             else ShipList[ShipList.Count-1].SetActive(false);
         }
     }

but if i would start over i'd do it like this:

private void Start()
 {
     ShipUpgradeLeft.GetComponent<Button>().onClick.AddListener(() => { Previous(); });
     ShipUpgradeRight.GetComponent<Button>().onClick.AddListener(() => { Next(); });
 }
 public void Next()
 {
     ShipList[shipUpgradeSelected].SetActive(false);
     shipUpgradeSelected = Mathf.Clamp(shipUpgradeSelected++, 0, ShipList.Count - 1);
     ShipList[shipUpgradeSelected].SetActive(true);
 }
 public void Previous()
 {
     ShipList[shipUpgradeSelected].SetActive(false);
     shipUpgradeSelected = Mathf.Clamp(shipUpgradeSelected--, 0, ShipList.Count - 1);
     ShipList[shipUpgradeSelected].SetActive(true);
 }

Thanks to walther and d12frosted for helping me solve the issue

Dane Gillis
  • 137
  • 1
  • 3
  • 14