using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; // 导航栏控制器 public class NavbarController : MonoBehaviour { [Serializable] public class NavItem { [Tooltip("导航栏按钮组件")] public Button button; [Tooltip("需要控制显示/隐藏的右侧页面")] public GameObject targetPanel; [Tooltip("高亮指示器;如果它是按钮的子物体,可自动查找")] public Image Indicator; } [Header("导航项配置")] public List navItems = new List(); [Header("外观设置")] public Color selectedColor = new Color(0f, 0.282f, 1f, 1f); public Color hoverColor = new Color(0.122f, 0.122f, 0.122f, 1f); // 当前选中的索引,-1 表示没有选中项 private int currentIndex = -1; private void Start() { InitializeNavigation(); AutoSelectFirstValidItem(); } // 在编辑器中自动补全按钮子物体中的高亮指示器。 private void OnValidate() { ResolveAutomaticReferences(); } private void InitializeNavigation() { ResolveAutomaticReferences(); for (int i = 0; i < navItems.Count; i++) { NavItem item = navItems[i]; if (!ValidateNavItem(item)) continue; SetItemActive(item, false); int itemIndex = i; item.button.onClick.AddListener(() => OnNavButtonClick(itemIndex)); } } private void OnNavButtonClick(int targetIndex) { SwitchToPanel(targetIndex); } private void SwitchToPanel(int newIndex) { if (!IsValidIndex(newIndex) || newIndex == currentIndex) return; NavItem newItem = navItems[newIndex]; if (!ValidateNavItem(newItem)) return; if (IsValidIndex(currentIndex)) { NavItem previousItem = navItems[currentIndex]; if (ValidateNavItem(previousItem)) SetItemActive(previousItem, false); } SetItemActive(newItem, true); currentIndex = newIndex; } private void SetItemActive(NavItem item, bool isSelected) { item.targetPanel.SetActive(isSelected); SetBtnVisualState(item, isSelected, false); } private void SetBtnVisualState(NavItem item, bool isSelected, bool isHovered) { if (item == null || item.Indicator == null) return; bool shouldShow = isSelected || isHovered; item.Indicator.gameObject.SetActive(shouldShow); if (shouldShow) item.Indicator.color = isSelected ? selectedColor : hoverColor; } private void AutoSelectFirstValidItem() { for (int i = 0; i < navItems.Count; i++) { if (ValidateNavItem(navItems[i])) { SwitchToPanel(i); return; } } Debug.LogError("没有找到有效的导航项配置!"); } private bool ValidateNavItem(NavItem item) { bool isValid = item != null && item.button != null && item.targetPanel != null && item.Indicator != null; if (!isValid) { Debug.LogWarning("发现无效导航项配置,请检查以下对象:\n" + $"Button: {item?.button?.name ?? "null"}\n" + $"Panel: {item?.targetPanel?.name ?? "null"}\n" + $"Indicator: {item?.Indicator?.name ?? "null"}"); } return isValid; } // 根据约定自动查找按钮子物体中名称以 Indicator 结尾的 Image。 private void ResolveAutomaticReferences() { if (navItems == null) return; foreach (NavItem item in navItems) { if (item == null || item.button == null || item.Indicator != null) continue; Image[] images = item.button.GetComponentsInChildren(true); foreach (Image image in images) { if (image != item.button.image && image.name.EndsWith("Indicator", StringComparison.OrdinalIgnoreCase)) { item.Indicator = image; break; } } } } private bool IsValidIndex(int index) { return index >= 0 && index < navItems.Count; } // 用于 Event Trigger:指针进入 public void OnPointerEnter(int itemIndex) { if (!IsValidIndex(itemIndex) || itemIndex == currentIndex) return; SetBtnVisualState(navItems[itemIndex], false, true); } // 用于 Event Trigger:指针离开 public void OnPointerExit(int itemIndex) { if (!IsValidIndex(itemIndex) || itemIndex == currentIndex) return; SetBtnVisualState(navItems[itemIndex], false, false); } }