You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何实现按钮组选中色保留至同组其他按钮被选中

问题根因

UGUI原生Button的选中高亮状态完全绑定EventSystem的currentSelectedGameObject属性,只要点击任意其他可交互UI组件(包括页面内的功能按钮、输入框、下拉框等),EventSystem会自动将当前选中对象更新为新点击的UI,原底部导航按钮的选中态会被直接清除。这不是组件bug,是原生逻辑的设计目标是适配表单类UI的焦点切换,本来就不符合底部导航常驻选中的交互需求。
之前尝试加Toggle组件无法实现效果,本质是因为Toggle的选中状态同样受EventSystem焦点逻辑控制,且需要配合ToggleGroup做互斥,还要处理Toggle值变化和页面切换的双向同步,冗余逻辑多,不做自定义适配没法直接满足导航栏需求。

完整落地实现方案

第一步:重构导航栏管理逻辑,手动维护选中状态

彻底放弃依赖UGUI原生Button/Toggle的自动选中逻辑,自己控制导航按钮的状态,从根源上和EventSystem的焦点切换逻辑解耦。
把原来挂载在导航栏父物体上的脚本替换为以下代码:

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;

public class BottomNavigationManager : MonoBehaviour
{
    [Header("页面配置,顺序和导航按钮一一对应")]
    public List<GameObject> Screens = new List<GameObject>();
    [Header("底部导航按钮配置,顺序和页面一一对应")]
    public List<Button> NavButtons = new List<Button>();
    public Color normalColor = Color.white;
    public Color selectedColor = Color.green;

    private int currentActiveIndex = 0;

    private void Start()
    {
        // 自动给所有导航按钮绑定切换事件
        for (int i = 0; i < NavButtons.Count; i++)
        {
            int cacheIndex = i; // 闭包缓存索引,避免回调索引错乱
            NavButtons[i].onClick.AddListener(() =>
            {
                SwitchToPage(cacheIndex);
            });
        }
        // 初始化默认显示第一个页面
        SwitchToPage(0);
    }

    /// <summary>
    /// 按索引切换页面
    /// </summary>
    /// <param name="pageIndex">目标页面索引</param>
    public void SwitchToPage(int pageIndex)
    {
        if (pageIndex < 0 || pageIndex >= Screens.Count) return;

        // 切换页面显隐
        for (int i = 0; i < Screens.Count; i++)
        {
            Screens[i].SetActive(i == pageIndex);
        }

        // 手动刷新所有导航按钮的显示状态
        for (int i = 0; i < NavButtons.Count; i++)
        {
            ColorBlock buttonColors = NavButtons[i].colors;
            // 同步所有状态下的颜色,避免悬停、点击时颜色异常
            buttonColors.normalColor = i == pageIndex ? selectedColor : normalColor;
            buttonColors.highlightedColor = i == pageIndex ? selectedColor : normalColor;
            buttonColors.selectedColor = i == pageIndex ? selectedColor : normalColor;
            buttonColors.pressedColor = selectedColor;
            NavButtons[i].colors = buttonColors;

            // 如果需要切换选中图标、播放选中动效,在这里加逻辑即可
        }

        currentActiveIndex = pageIndex;
    }

    // 兼容原有通过传GameObject切换页面的绑定逻辑,不需要修改之前编辑器里的事件配置
    public void OnClickBottomNavigationButton(GameObject activeScreen)
    {
        int targetIndex = Screens.IndexOf(activeScreen);
        SwitchToPage(targetIndex);
    }
}

脚本挂好后,在Inspector面板把5个页面对象拖到Screens列表,把5个底部导航按钮拖到NavButtons列表,保证两个列表顺序一一对应即可。

第二步:关闭EventSystem默认的失焦逻辑

选中场景中的EventSystem对象,找到挂载的Standalone Input Module组件,取消勾选Deselect On Background Click选项,解决点击空白区域时选中态丢失的问题。

第三步:效果验证

完成以上配置后,不管点击屏幕空白区域、页面内的其他功能按钮(比如Home页的"Buy Coins"按钮),底部导航栏的选中状态都会常驻在当前激活页面对应的按钮上,不会异常消失。

注意:不要给导航按钮添加Toggle组件,原生Button组件即可满足需求。如果后续需要新增导航按钮/页面,只需要在两个列表中按顺序添加对应引用,不需要修改代码逻辑。

原有方案的问题说明
  • 初始版本点任意区域就丢选中:一方面是Standalone Input Module默认开启了点空白取消选中,另一方面点击其他可交互UI时EventSystem会自动切换焦点,原生Button的选中态完全依赖焦点,自然会丢失。
  • 之前参考的社区方案只能解决空白区域点击的问题,没有处理其他UI按钮点击时的焦点切换,本质还是没脱离对原生选中逻辑的依赖,所以会出现点其他按钮就丢状态的问题。

内容的提问来源于stack exchange,提问作者chethan venkataramaiah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 20:39:18