Mutually exclusive toggle buttons?

Howdy folks. Here is my question for today.

I am trying to make some mutually exclusive toggle buttons to select one option from a set of options.

The problem I have is that when you click on any of the toggle buttons it does not behave quite the way I want.
What I am looking for is for each toggle to toggle on when clicked, and for it to toggle off the others in the same group if they are on.

What I don’t want is if I click on a toggle that is on, for it to turn off and turn on one of the others, which is what this code does.

Can anyone shed some light on how I would achieve the effect I am looking for?

I am able to set a GUILayout.Toggle to be one of two options by doing this:

OptonOne = GUILayout.Toggle(!OptionTwo, "OptonOne");
OptionTwo = GUILayout.Toggle(!OptonOne, "OptionTwo");

This only allows one of the toggles to be true at a time.

I want to have four mutually exclusive options and it kind of works if I do this:

OptionThree = GUILayout.Toggle(!OptionFour  !OptionFive  !OptionSix, new GUIContent("OptionThree", ""));

OptionFour = GUILayout.Toggle(!OptionThree  !OptionFive  !OptionSix, new GUIContent("OptionFour", ""));

OptionFive = GUILayout.Toggle(!OptionThree  !OptionFour  !OptionSix, new GUIContent("OptionFive", ""));

OptionSix = GUILayout.Toggle(!OptionThree  !OptionFour  !OptionFive, new GUIContent("OptionSix", ""));

If you try more than four at once crashes Unity. :frowning:

I’m not getting a crash when I add an extra option with this code. Can you post the code that crashes Unity when you use it?

you may find the GUI toolbar or selectionGrid elements may suit what you are doing better. They can contain buttons whose on state is mutually exclusive. You pass in the index of the active button and it returns the index of the active button or a new selection.

it crashes if you use somthing like this:

OptionSeven = GUILayout.Toggle(!OptionThree  !OptionFour  !OptionFive, !OptionSix, new GUIContent("OptionSix", ""));

Thanks, I will give that a try.

This has been asked a while ago, I know, but I found an easier way and it may help other people looking for a solution (I had many toggles on same group) This is probable not an elegant solution but I’m still a newbie…

//declaration
private bool q1a;
private bool q1b;
private bool q1c;

void OnGUI(){
  change1a(GUI.Toggle(new Rect(10,10,10,10),q1a,""));
  change1b(GUI.Toggle(new Rect(30,10,10,10),q1b,""));
  change1c(GUI.Toggle(new Rect(50,10,10,10),q1c,""));
}

private void change1a(bool newvalue){
  if(newvalue){
    q1b = false;
    q1c = false;
  }
  q1a = newvalue;
}

private void change1b(bool newvalue){
  if(newvalue){
    q1a = false;
    q1c = false;
  }
  q1b = newvalue;
}

private void change1c(bool newvalue){
  if(newvalue){
    q1a = false;
    q1b = false;
  }
  q1c = newvalue;
}

Hope this help !

        /// <summary>
        /// Displays a vertical list of toggles and returns the index of the selected item.
        /// </summary>
        public static int ToggleList(int selected, GUIContent[] items)
        {
            // Keep the selected index within the bounds of the items array
            selected = selected < 0 ? 0 : selected >= items.Length ? items.Length - 1 : selected;

            GUILayout.BeginVertical();
            for (int i = 0; i < items.Length; i++)
            {
                // Display toggle. Get if toggle changed.
                bool change = GUILayout.Toggle(selected == i, items[i]);
                // If changed, set selected to current index.
                if (change)
                    selected = i;
            }
            GUILayout.EndVertical();

            // Return the currently selected item's index
            return selected;
        }

This will allow you to put in an array of GUIContents as your items, so all you have to do is check items[selected] to see what is selected. This can be modified to automatically come with a ScrollView as well, if needed, though it works fine as-is. I tested it with four items, but virtually any length will work fine.

EDIT:

Alternatively, you can use SelectionGrid and assign it the GUI.skin.toggle GUISkin, which will result in a similar looking control. However, I notice a bit of a pause in the control state graphics changes using this method (I mean, when you select a toggle, it pauses at the Clicked graphic for a moment before moving to the selected graphic). So either method works, but mine does not have the pause so far as I can tell.

2 Likes