Search Unity

Unity UI [Bug]Toggle Group In Unity 2019.2.0a9

Discussion in 'Unity UI (uGUI) & TextMesh Pro' started by linfuqing, Mar 28, 2019.

  1. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    60
    1.I have 3 toggles with the same ToggleGroup.like this:
    upload_2019-3-28_15-36-26.png upload_2019-3-28_15-37-17.png upload_2019-3-28_15-45-45.png
    2.I disable the "Canvas" and enable it.The selected toggle will be changed to:
    upload_2019-3-28_15-43-37.png

    It's a bug?
     

    Attached Files:

    Khonkaengame likes this.
  2. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    60
  3. JoeyHe

    JoeyHe

    Joined:
    Jun 10, 2014
    Posts:
    1
    I had the same problem, has anybody solved it?
     
  4. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    60
    Code (CSharp):
    1.     public class ToggleEx : Toggle
    2.     {
    3.         private struct Group
    4.         {
    5.             public HashSet<ToggleEx> onToggles;
    6.             public HashSet<ToggleEx> offToggles;
    7.         }
    8.  
    9.         private static Dictionary<ToggleGroup, Group> __groups;
    10.  
    11.         private bool __isOn;
    12.         private ToggleGroup __group;
    13.  
    14.         protected override void Awake()
    15.         {
    16.             base.Awake();
    17.  
    18.             __isOn = isOn;
    19.  
    20.             ToggleGroup group = base.group;
    21.             if (group != null)
    22.             {
    23.                 __group = group;
    24.  
    25.                 __Add();
    26.             }
    27.  
    28.             if (onValueChanged == null)
    29.                 onValueChanged = new ToggleEvent();
    30.  
    31.             onValueChanged.AddListener(__Update);
    32.         }
    33.  
    34.         protected override void OnEnable()
    35.         {
    36.             if (!__isOn && __group != null)
    37.             {
    38.                 Group group;
    39.                 if (__groups != null && __groups.TryGetValue(__group, out group) && group.onToggles != null)
    40.                 {
    41.                     foreach (ToggleEx toggle in group.onToggles)
    42.                         __group.RegisterToggle(toggle);
    43.                 }
    44.             }
    45.  
    46.             base.OnEnable();
    47.         }
    48.  
    49.         protected override void OnDisable()
    50.         {
    51.             if (__isOn && __group != null)
    52.             {
    53.                 Group group;
    54.                 if (__groups != null && __groups.TryGetValue(__group, out group) && group.offToggles != null)
    55.                 {
    56.                     foreach (ToggleEx toggle in group.offToggles)
    57.                         __group.UnregisterToggle(toggle);
    58.                 }
    59.             }
    60.  
    61.             base.OnDisable();
    62.         }
    63.  
    64.         protected override void OnDestroy()
    65.         {
    66.             __Remove();
    67.  
    68.             base.OnDestroy();
    69.         }
    70.  
    71.         private void __Add()
    72.         {
    73.             if (__group == null)
    74.                 return;
    75.  
    76.             if (__groups == null)
    77.                 __groups = new Dictionary<ToggleGroup, Group>();
    78.  
    79.             Group group;
    80.             __groups.TryGetValue(__group, out group);
    81.  
    82.             if (__isOn)
    83.             {
    84.                 if (group.onToggles == null)
    85.                     group.onToggles = new HashSet<ToggleEx>();
    86.  
    87.                 group.onToggles.Add(this);
    88.  
    89.                 __groups[__group] = group;
    90.             }
    91.             else
    92.             {
    93.                 if (group.offToggles == null)
    94.                     group.offToggles = new HashSet<ToggleEx>();
    95.  
    96.                 group.offToggles.Add(this);
    97.  
    98.                 __groups[__group] = group;
    99.             }
    100.         }
    101.  
    102.         private void __Remove()
    103.         {
    104.             if (__group == null)
    105.                 return;
    106.  
    107.             if (__groups == null)
    108.                 __groups = new Dictionary<ToggleGroup, Group>();
    109.  
    110.             Group group;
    111.             __groups.TryGetValue(__group, out group);
    112.  
    113.             if (__isOn)
    114.             {
    115.                 if (group.onToggles != null)
    116.                     group.onToggles.Remove(this);
    117.  
    118.                 __groups[__group] = group;
    119.             }
    120.             else
    121.             {
    122.                 if (group.offToggles != null)
    123.                     group.offToggles.Remove(this);
    124.  
    125.                 __groups[__group] = group;
    126.             }
    127.         }
    128.  
    129.         private void __Update(bool value)
    130.         {
    131.             __Remove();
    132.  
    133.             __isOn = value;
    134.  
    135.             __group = group;
    136.  
    137.             __Add();
    138.         }
    139.     }
    this's my temporary solutions.
     
    Zdreni likes this.
  5. Checko

    Checko

    Joined:
    Oct 23, 2013
    Posts:
    16
  6. NobleRobot

    NobleRobot

    Joined:
    Jan 14, 2016
    Posts:
    33
    For anyone looking for a lightweight workaround:

    Ultimately, all you need to avoid this issue is for "toggleGroup.allowSwitchOff" to be true before your "menu" is "disabled," which triggers the bug. This is a friggin' hassle to do, but since I already have delegates which are called when enabling and disabling the objects that contain my ToggleGroups, I can change allowSwitchOff to be false only while the ToggleGroup is active.

    This is dependent on my own "MenuController" class and its "onMenuEnabled/onMenuDisabled" delegates, so you'll have to adjust this to fit your codebase as needed and make sure you cover your edge cases, but conceptually, this is a drop-in solution that adds practically no overhead at runtime. I also set this script to run early in the project's Script Execution Order, just in case.

    My actual version of this code uses
    GetComponent
    stuff to populate the needed variables at *build-time* using
    IProcessSceneWithReport
    , so that I can just drop this on a object with a ToggleGroup without having to configure it while also avoiding any overhead (however tiny) in Start or Awake, which I hate.

    .........

    Code (CSharp):
    1. public class ToggleGroupBugFixer : MonoBehaviour {
    2.  
    3.   // This is to fix a dumb bug in Unity 2019.1.
    4.  
    5.   [SerializeField] private MenuController menu;
    6.   [SerializeField] private ToggleGroup toggleGroup;
    7.  
    8.   private void Awake(){
    9.     menu.onMenuEnabled += menuEnabledHander;
    10.     menu.onMenuDisabled += menuDisabledHandler;
    11.   }
    12.   private void OnDestroy(){
    13.     menu.onMenuEnabled -= menuEnabledHander;
    14.     menu.onMenuDisabled -= menuDisabledHandler;
    15.   }
    16.  
    17.   private void menuEnabledHander(){
    18.     toggleGroup.allowSwitchOff = false;
    19.   }
    20.   private void menuDisabledHandler(){
    21.     toggleGroup.allowSwitchOff = true;
    22.   }
    23.  
    24. }
     
unityunity