// UXGroup.cs using UnityEngine; using UnityEngine.Events; using System.Collections.Generic; using Sirenix.OdinInspector; using UnityEngine.EventSystems; [DisallowMultipleComponent] public class UXGroup : UIBehaviour { [SerializeField] private bool m_AllowSwitchOff; [ReadOnly] [SerializeField] private List m_Buttons = new List(); private UXButton currentUXButton = null; public UnityEvent onSelectedChanged = new UnityEvent(); public bool allowSwitchOff { get => m_AllowSwitchOff; set { m_AllowSwitchOff = value; ValidateGroupState(); } } protected override void OnDestroy() { base.OnDestroy(); m_Buttons.Clear(); currentUXButton = null; } protected override void Awake() { base.Awake(); ValidateGroupState(); } public void RegisterButton(UXButton button) { if (!m_Buttons.Contains(button)) { m_Buttons.Add(button); if (button.IsSelected) { if (currentUXButton != null && currentUXButton != button) { currentUXButton.IsSelected = false; } currentUXButton = button; } ValidateGroupState(); } } public void UnregisterButton(UXButton button) { if (m_Buttons.Contains(button)) { m_Buttons.Remove(button); button.IsSelected = false; } } internal void NotifyButtonClicked(UXButton clickedButton) { if (!clickedButton.IsSelected) { SetSelectedButton(clickedButton); } else { if (m_AllowSwitchOff) SetSelectedButton(null); else if (currentUXButton != clickedButton) clickedButton.IsSelected = true; } } private void SetSelectedButton(UXButton targetButton) { UXButton previousSelected = currentUXButton; currentUXButton = null; // 防止递归 foreach (var button in m_Buttons) { bool shouldSelect = (button == targetButton); if (button.IsSelected != shouldSelect) { button.IsSelected = shouldSelect; } if (shouldSelect) currentUXButton = button; } if (previousSelected != currentUXButton) { onSelectedChanged.Invoke(currentUXButton); } } private void ValidateGroupState() { bool anySelected = m_Buttons.Exists(b => b.IsSelected); if (!anySelected && m_Buttons.Count > 0 && !m_AllowSwitchOff) { SetSelectedButton(m_Buttons[0]); } } public bool AnyOtherSelected(UXButton exclusion) { foreach (var button in m_Buttons) { if (button != exclusion && button.IsSelected) return true; } return false; } }