I’m trying, for the first time, to have two different groups of toggles on one screen. Yet despite each group referencing a different ToggleGroup, they act conjoined: selecting any button deselects all others, even the ones in the other group.
Here’s my setup:
UICanvas (Canvas)
SystemModeGroup (ToggleGroup)
Mode1 (Toggle, with Group set to SystemModeGroup)
Mode2 (Toggle, with Group set to SystemModeGroup)
Mode3 (Toggle, with Group set to SystemModeGroup)
TopFrame (just an empty GameObject which I’ll later make into a prefab)
DisplaySwitch (ToggleGroup)
MasterButton (Toggle, with Group set to DisplaySwitch)
SensorButton (Toggle, with Group set to DisplaySwitch)
DiagnosticButton (Toggle, with Group set to DisplaySwitch)
I know it’s not actually necessary to have the toggles set up as children of the ToggleGroup, but I prefer to keep things organized that way.
Anyway, when I run, I should be able to select (say) both Mode1 and DiagnosticButton. But instead, selecting Mode1 deselects all five other buttons. And so on for all the other buttons.
Sure looks like a bug to me, but am I missing something?
I’ve stripped down my project to a minimal example (only 36k zipped!). You can download it here. Just run the only scene in the project (SituationScene).
I’ve gone over it and over it, looking for something I might have done wrong in the setup, but I just don’t see it. If someone could point it out to me, I’d be much obliged!
bit of a hack, but if you add an image as a child to the toggle group and add a canvas group to it with “non interactable” and “doesn’t block raycasts” you can assign it to the “graphic” slot in the toggle attributes the image then shows when “ison” is true and doesn’t when it’s false
Ah, now that’s interesting… I trusted the color, never thought to check isOn.
And it could explain why this wasn’t noticed before… probably if you are changing images, rather than merely tinting as I’m doing here, it works OK. It’s just some glitch in the application of tint color.
Though it’s still weird, because I wouldn’t expect toggles in one ToggleGroup to have any opportunity to affect toggles in a different group at all. Definitely something fishy there. Unfortunately, while I’m certain I was able to simple “Edit Script” on something like ToggleGroup in the past, now it just brings up a file-not-found error in MonoDevelop, so I can’t trace through myself and see what’s going on.
I think the tinting is the same as it is on buttons, i.e. it’s highlighting the currently selected UI element… looks the same in the inspector at least.
OK. It’s true. I had completely misunderstood what the “highlighted color” was for. Must be a Windows thing, as I can’t imagine why you’d ever want a control to behave this way.
For the record: “highlighted” just means that the control has the focus. Like the Highlander (Highlighter?), there can be only one of these, among all the controls (Selectables) on the screen. It has absolutely nothing to do with whether a toggle is on or off.
A Toggle, out of the box, can only display its on/off state by showing/hiding the graphic referenced by its Graphic property. So if you want a toggle that shows its on/off state by changing color, then you have to work a bit harder.
OPTION 1: Add a child object with, say, a Raw Image component set to the color of your “on” state. Set its RectTransform to stretch to the full size of its parent. Drag this into the Graphic property of the Toggle. This works pretty well, though it seems inelegant.
OPTION 2: Create a script like the following, and attach it to the Toggle:
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
[RequireComponent(typeof(Toggle))]
[ExecuteInEditMode]
public class ToggleColor : MonoBehaviour {
#region Public Properties
public Color offColor = Color.blue;
public Color onColor = Color.cyan;
public float transitionTime = 0.1f;
#endregion
//--------------------------------------------------------------------------------
#region Private Properties
Toggle toggle;
Graphic graphic;
float lerpPos;
#endregion
//--------------------------------------------------------------------------------
#region MonoBehaviour Events
void Start() {
toggle = GetComponent<Toggle>();
graphic = GetComponent<RawImage>();
}
void Update() {
#if UNITY_EDITOR
toggle = GetComponent<Toggle>();
graphic = GetComponent<RawImage>();
float dt = 1;
#else
float dt = Time.deltaTime;
#endif
if (toggle == null || graphic == null) return;
lerpPos = Mathf.MoveTowards(lerpPos, toggle.isOn ? 1 : 0, dt / transitionTime);
graphic.color = Color.Lerp(offColor, onColor, lerpPos);
}
#endregion
}
This also seems inelegant. I’m not yet sure which solution I hate less. Both do get the job done, though.
And as for my bug report, it was bogus. ToggleGroup is working fine… and Toggle is working as designed (just not the way I wish it were designed). I’ll let the Unity folks know they can close that report.
is the better choice because it remains consistent with the default Toggle object that is created when adding a Toggle via the GameObject>UI>Toggle menu. It may seem inelegant, but it is implementing the Toggle Object in the way it was intended.
In this case you are changing the the “check-mark” image (identifying “on” state) to a different image, which happens to be an raw image of a certain color stretched to fit on top of the toggle object.
As an added note, in my application, my “toggle buttons” have a custom sprite used on them, so my “check-mark” image has the same sprite as the “toggle button” below it. A raw image cause a solid rectangle to cover the toggle button.