Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
4
Question by Linck · Jun 22, 2015 at 03:43 PM · uieventtoggle

How to have a callback when a toggle is clicked in a toggle group?

I want a callback funcion to be called when one of my toggles in a toggle group is clicked.

I thought about making something like this

foreach (Toggle t in toggles) { t.onValueChanged.AddListener(callback); }

but then the callback would be called twice, because one toggle was selected, and other was deselected.

Any ideas?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
10
Best Answer

Answer by thats_how_i_feel · Nov 26, 2015 at 11:41 AM

I made a class which inherits the ToggleGroup which has an OnChange event: https://gist.github.com/jmbeach/78c3e46669db89628fce#file-bettertogglegroup-cs

 using UnityEngine;
 using UnityEngine.UI;
 using System.Linq;
 
 public class BetterToggleGroup : ToggleGroup {
     public delegate void ChangedEventHandler(Toggle newActive);
 
     public event ChangedEventHandler OnChange;
     public void Start() {
         foreach (Transform transformToggle in gameObject.transform) {
             var toggle = transformToggle.gameObject.GetComponent<Toggle>();
             toggle.onValueChanged.AddListener((isSelected) => {
                 if (!isSelected) {
                     return;
                 }
                 var activeToggle = Active();
                 DoOnChange(activeToggle);
             });
         }
     }
     public Toggle Active() {
         return ActiveToggles().FirstOrDefault();
     }
 
     protected virtual void DoOnChange(Toggle newactive)
     {
         var handler = OnChange;
         if (handler != null) handler(newactive);
     }
 }

Add the above class to your project and replace the ToggleGroup script in the inspector with it. The class requires that all of the ToggleGroup's Toggles are children of it: Inspector view of toggle group To listen to the event, from another script use the following code:

 TglGroup = GameObject.Find("Toggle Group Name").GetComponent<BetterToggleGroup>();
 TglGroup.OnChange += TglGroup_OnChange;
 //...
 void TglGroup_OnChange(Toggle newActive)
 {
   Debug.Log(string.Format("Toggle {0} selected",newActive.name));
 }


a95xcut.png (29.6 kB)
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Linck · Nov 26, 2015 at 12:03 PM 0
Share

Cool. That might help people. I came up with a similar solution at the time.

avatar image
5

Answer by DoomGoober · Mar 13, 2020 at 01:10 AM

@thatshowifeel had a good answer. Here's a slightly improved, more modern version:

 using System.Linq;
 using UnityEngine;
 using UnityEngine.Events;
 using UnityEngine.UI;
 
 [RequireComponent(typeof(ToggleGroup))]
 public class EventToggleGroup : MonoBehaviour
 {
     [System.Serializable]
     public class ToggleEvent : UnityEvent<Toggle> { }
 
     [SerializeField]
     public ToggleEvent onActiveTogglesChanged;
 
     [SerializeField]
     private Toggle[] _toggles;
 
     private ToggleGroup _toggleGroup;
 
     private void Awake()
     {
         _toggleGroup = GetComponent<ToggleGroup>();
     }
 
     // Start is called before the first frame update
     void OnEnable()
     {
         foreach (Toggle toggle in _toggles)
         {
             if (toggle.group != null && toggle.group != _toggleGroup)
             {
                 Debug.LogError($"EventToggleGroup is trying to register a Toggle that is a member of another group.");
             }
             toggle.group = _toggleGroup;
             toggle.onValueChanged.AddListener(HandleToggleValueChanged);
         }
     }
 
     void HandleToggleValueChanged(bool isOn)
     {
         if (isOn)
         {
             onActiveTogglesChanged?.Invoke(_toggleGroup.ActiveToggles().FirstOrDefault());
         }
     }
 
     void OnDisable()
     {
         foreach (Toggle toggle in _toggleGroup.ActiveToggles())
         {
             toggle.onValueChanged.RemoveListener(HandleToggleValueChanged);
             toggle.group = null;
         }
     }
 }
 

To use:

1) Add EventToggleGroup as a sibling of ToggleGroup.
2) Drag Toggle into EventToggleGroup.toggles.
3) Add something to listen to onActiveToggleChanged. Note: It may return null if no toggles are selected!

alt text

Changes:

*Rather than assuming the Toggles are children of the ToggleGroup transform you must explicitly specify the toggles. This allows you to put the ToggleGroup/EventToggleGroup wherever you want in the GameObject hierarchy.

*It is not necessary to specify the "group" on the individual Toggle components anymore. (Note: This does allow a toggle to be a member of multiple EventToggleGroups! Don't do this.)

*Rather than deriving from ToggleGroup, EventToggleGroup is a sibling component of ToggleGroup. This conforms to the Entity/Component model better.

*Rather than raising a C# event, it raises a UnityEvent which allows us to hook up event listeners in the UnityEditor AND code.


eventtogglegroup.png (32.3 kB)
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image adieu2 · Dec 01, 2020 at 09:43 AM 0
Share

Wow this is exactly what I needed! I don't really understand why there is not a class already built in Unity.

I think there is a typo line 49, shouldn't it be _toggles instead of _toggleGroup.ActiveToggles()?

avatar image fraeri · May 16, 2021 at 08:28 AM 0
Share

Loving that answer as well. I added the functionality, that the Group also fires the invoke if every toggle gets turned of by modifying the HandleToggleValueChanged-Function and adding CheckIfAllOff:

     void HandleToggleValueChanged(bool isOn)
     {
         if (isOn)
         {
             onActiveTogglesChanged?.Invoke(_toggleGroup.ActiveToggles().FirstOrDefault());
         }
         else
         {
             CheckIfAllOff();
         }
     }
 
     void CheckIfAllOff()
     {
         bool allOff = true;
         foreach (Toggle toggle in _toggleGroup.ActiveToggles())
         {
             if (toggle.isOn)
                 allOff = false;
         }
 
         if (allOff)
             onActiveTogglesChanged.Invoke(null);
     }
avatar image
0

Answer by MarcoSoldati · May 21, 2021 at 08:48 AM

Great solution. Thanks. I added a small function to set one option to 'on' and disable the others (useful for radio buttons).

     /**
      * Programmatically set a toggle to on (and set all others to off).
      */
     public void SetToggle(Toggle toggle)
     {
         foreach (Toggle t in Toggles)
         {
             bool isOn = toggle == t;
             t.isOn = isOn;
             Debug.Log(("setting " + t.name + " to " + isOn));
         }
     }
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image MarcoSoldati · May 21, 2021 at 08:51 AM 0
Share

@DoomGoober line 49 it would be more failure safe to use _toggles instead of ActiveToggles()

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

9 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Is there an event other than OnValueChanged for Toggle UI? 0 Answers

Toggle's 'On Value Changed' checkbox is shown for bool parameter function 0 Answers

Toggle Event passing bool [4.6+] 2 Answers

Is there a way to know when mouse is 'hovering' over a Toggle? 2 Answers

How can I reference a Toggle? 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges