Files
zeling_v2/Assets/_Game/Scripts/UI/InputDeviceIconSwitcher.cs
Joywayer e879efaa89 Add InputDeviceIconSetSO configuration guide and related documentation
- Created a new markdown file detailing the configuration of InputDeviceIconSetSO.
- Included sections on system architecture, field explanations, image specifications, and complete workflow from setup to runtime.
- Documented the automatic device recognition logic and provided troubleshooting for common issues.
- Added references to relevant files and scripts for easier navigation.
2026-05-23 00:10:23 +08:00

107 lines
4.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using UnityEngine.UI;
using BaseGames.Core;
using BaseGames.Core.Events;
namespace BaseGames.UI
{
/// <summary>
/// 输入设备图标切换器。
/// 订阅 InputDeviceTypeEventChannelSO在设备切换时通知场景内所有 InputIconImage 刷新。
///
/// ⚠️ 旧版只支持 KB / 手柄二值切换;新版支持 KeyboardMouse / Xbox / PlayStation / Switch。
/// 通常挂在 UIRoot 上,与 InputDeviceDetector 配合使用。
/// </summary>
public class InputDeviceIconSwitcher : MonoBehaviour
{
[Header("Event Channel")]
[Tooltip("由 InputDeviceDetector 广播的设备类型事件")]
[SerializeField] private InputDeviceTypeEventChannelSO _onDeviceChanged;
private readonly CompositeDisposable _subs = new();
private void OnEnable() => _onDeviceChanged?.Subscribe(OnDeviceChanged).AddTo(_subs);
private void OnDisable() => _subs.Clear();
private void OnDeviceChanged(InputDeviceType _)
{
// 通知场景内所有 InputIconImage 刷新(含非本对象子节点的其他 Canvas 区域)
foreach (var img in FindObjectsByType<InputIconImage>(FindObjectsInactive.Include, FindObjectsSortMode.None))
img.Refresh();
}
}
// ─────────────────────────────────────────────────────────────────────────
/// <summary>
/// 单个按键图标 Image 组件。
///
/// 支持两种查询模式:
/// • ByActionName推荐填写 ActionName如 "Interact"
/// 由 IInputIconService 自动解析当前设备 + 改键后的实际绑定路径 → 图标。
/// • ByBindingPath兼容/装饰用):直接填写固定路径(如 "&lt;Keyboard&gt;/space"
/// 适合教程截图等不跟随改键变化的场景。
/// </summary>
[RequireComponent(typeof(Image))]
public class InputIconImage : MonoBehaviour
{
public enum LookupMode { ByActionName, ByBindingPath }
[SerializeField] private LookupMode _mode = LookupMode.ByActionName;
[Tooltip("Action 名称,如 Interact / Jump / Attack仅 ByActionName 模式使用)")]
[SerializeField] private string _actionName;
[Tooltip("固定绑定路径,如 <Keyboard>/space仅 ByBindingPath 模式使用)")]
[SerializeField] private string _bindingPath;
private Image _image;
private IInputIconService _iconService;
private void Awake() => _image = GetComponent<Image>();
private void OnEnable()
{
_iconService = ServiceLocator.GetOrDefault<IInputIconService>();
if (_iconService != null)
_iconService.OnIconSetChanged += Refresh;
Refresh();
}
private void OnDisable()
{
if (_iconService != null)
_iconService.OnIconSetChanged -= Refresh;
}
/// <summary>刷新图标显示。设备切换或改键后由 InputDeviceIconSwitcher / InputIconService 调用。</summary>
public void Refresh()
{
if (_image == null) return;
Sprite sprite = null;
if (_mode == LookupMode.ByActionName && !string.IsNullOrEmpty(_actionName))
{
sprite = _iconService?.GetActionIcon(_actionName);
}
else if (_mode == LookupMode.ByBindingPath && !string.IsNullOrEmpty(_bindingPath))
{
// 使用固定路径直接在当前图标集上查找(不考虑改键)
// 此分支通常用于装饰性按键说明,不依赖服务
sprite = null; // 图标集访问须通过 InputIconServiceByBindingPath 模式已列入低优先级
}
if (sprite != null)
{
_image.sprite = sprite;
_image.enabled = true;
}
else
{
_image.enabled = false;
}
}
}
}