Unity按钮动画问题:方向键垂直切换已实现,鼠标交互失效求助
Unity按钮交互冲突与动态生成解决方案
一、修复方向键动画与鼠标动画冲突问题
核心是用同一Animator Controller统一管理所有交互状态,避免两套动画逻辑互相覆盖。
1. 配置Animator状态机
创建一个Animator Controller,包含4个状态:
- Normal:默认状态
- Selected:方向键选中时的状态
- Hover:鼠标悬停时的状态
- Pressed:点击时的状态
状态切换条件设置:
- Normal ↔ Selected:通过布尔参数
IsSelected控制 - Normal ↔ Hover:通过布尔参数
IsHovered控制 - 所有状态 → Pressed:通过触发参数
OnPressed控制,Pressed自动回到对应前置状态(比如从Selected进入Pressed,退出后回到Selected)
2. 挂载状态同步脚本
给每个按钮添加如下脚本,统一处理方向键选中和鼠标交互的状态同步:
using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; public class ButtonStateController : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler { private Animator _animator; private Button _button; private void Awake() { _animator = GetComponent<Animator>(); _button = GetComponent<Button>(); } // 由导航脚本调用,设置方向键选中状态 public void SetSelected(bool isSelected) { _animator.SetBool("IsSelected", isSelected); // 选中时强制关闭hover状态,避免冲突 if (isSelected) { _animator.SetBool("IsHovered", false); } } public void OnPointerEnter(PointerEventData eventData) { // 只有未被方向键选中时,才触发hover动画 if (!_animator.GetBool("IsSelected")) { _animator.SetBool("IsHovered", true); } } public void OnPointerExit(PointerEventData eventData) { _animator.SetBool("IsHovered", false); } public void OnPointerClick(PointerEventData eventData) { _animator.SetTrigger("OnPressed"); // 执行按钮点击逻辑 _button.onClick?.Invoke(); } }
3. 适配原有方向键导航脚本
修改你原有的方向键切换脚本,确保选中按钮时调用SetSelected方法:
using UnityEngine; using UnityEngine.UI; public class MenuNavigation : MonoBehaviour { public ButtonStateController[] buttons; private int _currentSelectedIndex = 0; private void Start() { // 默认选中第一个按钮 buttons[_currentSelectedIndex].SetSelected(true); } private void Update() { if (Input.GetKeyDown(KeyCode.DownArrow)) { Navigate(1); } else if (Input.GetKeyDown(KeyCode.UpArrow)) { Navigate(-1); } } private void Navigate(int direction) { // 取消当前选中按钮的状态 buttons[_currentSelectedIndex].SetSelected(false); // 计算新的选中索引 _currentSelectedIndex += direction; _currentSelectedIndex = Mathf.Clamp(_currentSelectedIndex, 0, buttons.Length - 1); // 设置新选中按钮的状态 buttons[_currentSelectedIndex].SetSelected(true); // 可选:让EventSystem同步选中状态,确保键盘输入正常 EventSystem.current.SetSelectedGameObject(buttons[_currentSelectedIndex].gameObject); } }
二、自动生成按钮的兼容性处理
自动生成按钮时,只需要确保以下几点,就能保留方向键切换功能:
1. 动态维护按钮列表
在导航脚本中用List<ButtonStateController>替代数组,生成按钮时自动添加到列表:
using UnityEngine; using UnityEngine.UI; using System.Collections.Generic; public class DynamicMenuNavigation : MonoBehaviour { public Button buttonPrefab; public Transform buttonParent; private List<ButtonStateController> _buttons = new List<ButtonStateController>(); private int _currentSelectedIndex = 0; public void GenerateButtons(string[] buttonTexts) { // 清空原有按钮 foreach (Transform child in buttonParent) { Destroy(child.gameObject); } _buttons.Clear(); // 生成新按钮 foreach (string text in buttonTexts) { Button newButton = Instantiate(buttonPrefab, buttonParent); newButton.GetComponentInChildren<Text>().text = text; ButtonStateController stateController = newButton.GetComponent<ButtonStateController>(); if (stateController == null) { stateController = newButton.AddComponent<ButtonStateController>(); } _buttons.Add(stateController); } // 默认选中第一个按钮 if (_buttons.Count > 0) { _buttons[_currentSelectedIndex].SetSelected(true); } } // 导航逻辑和之前的MenuNavigation一致,把数组换成_buttons列表即可 private void Update() { if (_buttons.Count == 0) return; if (Input.GetKeyDown(KeyCode.DownArrow)) { Navigate(1); } else if (Input.GetKeyDown(KeyCode.UpArrow)) { Navigate(-1); } } private void Navigate(int direction) { _buttons[_currentSelectedIndex].SetSelected(false); _currentSelectedIndex += direction; _currentSelectedIndex = Mathf.Clamp(_currentSelectedIndex, 0, _buttons.Count - 1); _buttons[_currentSelectedIndex].SetSelected(true); EventSystem.current.SetSelectedGameObject(_buttons[_currentSelectedIndex].gameObject); } }
2. 预制体配置
确保按钮预制体已经添加了Button、Animator(绑定好之前的状态机)、ButtonStateController组件,这样生成的每个按钮都自带完整的交互逻辑。
内容的提问来源于stack exchange,提问作者Han1t
相关产品推荐
相关产品推荐

