Unity接入遥控器/手柄

需求分析

项目中需要接入遥控器,代替键鼠,以及替代触屏

改造内容

1.需要UI上进行适配:需要设置UI的Selected和Normal状态进行明显区分,当选中时会显示Selected的状态。效果较好的是UI本身作为一个底图或描边,不影响前面显示的图片

2.代码方面:需要设置选中的Selectable,传给EventSystem.current.SetSelectedGameObject( ),上下左右移动需要监听到按键事件的时候先获取到对应方向的UI : current.FindSelectableOnUp() ,然后进行移动。

3.交互优化:界面上尽可能不要有多层可交互的UI并且互相遮挡,除非手动指定按钮的上下左右对应的UI,否则可能会随时选到被遮挡的UI。

示例代码

RemoteControlNavigation.cs

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class RemoteControlNavigation : MonoBehaviour
{
    public static RemoteControlNavigation Instance;
    private void Awake()
    {
        Instance = this;
    }
    public Selectable firstSelected;

    public float inputDelay = 0.15f;

    public Transform currentUIRoot;

    public Selectable current;
    private float lastInputTime;


    public Selectable firstSelected2;
    public Transform currentUIRoot2;

    public Selectable current2;
    public bool isOnlyBtn;
    void Start()
    {

        if(isOnlyBtn)
        {
            firstSelected = gameObject.GetComponent<Selectable>();
            current = gameObject.GetComponent<Selectable>();
            currentUIRoot = transform.parent;
        }
        else
        {
            if (LoginManager.Instance.isUser1Login || LoginManager.Instance.isUser2Login || LoginManager.Instance.isUser3Login || LoginManager.Instance.isUser4Login||
                LoginManager.Instance.isUser1VisitorLogin || LoginManager.Instance.isUser2VisitorLogin || LoginManager.Instance.isUser3VisitorLogin || LoginManager.Instance.isUser4VisitorLogin)
            {
                firstSelected = firstSelected2;
                current = current2;
                currentUIRoot = currentUIRoot2;
            }
        }


      
        Debug.LogError(currentUIRoot == null);
        Debug.LogError(firstSelected == null);
        Debug.LogError(firstSelected.transform == null);
        Debug.LogError(firstSelected.transform.root == null);
        // 如果没指定UI根节点,就用当前物体所在的Canvas
        if (currentUIRoot == null)
            currentUIRoot = firstSelected.transform.root;

        current = firstSelected;
        if (current != null)
            EventSystem.current.SetSelectedGameObject(current.gameObject);
    }

    void Update()
    {


        if(isOnlyBtn) //返回
        {
            if(Input.GetKeyDown((KeyCode)System.Enum.Parse(typeof(KeyCode),XMLConfigData.instance.Back)))
            {
                SceneManager.LoadScene("MenuScene");
            }
        }

        if (Time.time - lastInputTime < inputDelay)
            return; // 防抖

        bool moved = false;

        // 上下左右导航
        if (Input.GetKeyDown((KeyCode)System.Enum.Parse(typeof(KeyCode), XMLConfigData.instance.Up)))
        {
            MoveTo(current.FindSelectableOnUp());
            moved = true;
        }
        else if (Input.GetKeyDown((KeyCode)System.Enum.Parse(typeof(KeyCode), XMLConfigData.instance.Down)))
        {
            MoveTo(current.FindSelectableOnDown());
            moved = true;
        }
        else if (Input.GetKeyDown((KeyCode)System.Enum.Parse(typeof(KeyCode), XMLConfigData.instance.Left)))
        {
            MoveTo(current.FindSelectableOnLeft());
            moved = true;
        }
        else if (Input.GetKeyDown((KeyCode)System.Enum.Parse(typeof(KeyCode), XMLConfigData.instance.Right)))
        {
            MoveTo(current.FindSelectableOnRight());
            moved = true;
        }

        // 确认键(回车)
        if (Input.GetKeyDown((KeyCode)System.Enum.Parse(typeof(KeyCode), XMLConfigData.instance.Enter)))
        {
            if (current != null)
            {
                ExecuteEvents.Execute(current.gameObject, new BaseEventData(EventSystem.current), ExecuteEvents.submitHandler);
            }
        }

        if (moved)
            lastInputTime = Time.time;
    }

    void MoveTo(Selectable next)
    {
        if (next != null && IsInCurrentUIRoot(next))
        {
            current = next;
            EventSystem.current.SetSelectedGameObject(current.gameObject);
        }
    }

    bool IsInCurrentUIRoot(Selectable target)
    {
        return target.transform.IsChildOf(currentUIRoot);
    }

    /// <summary>
    /// 切换UI焦点范围(比如从背景切到弹窗)
    /// </summary>
    public void SetUIRoot(Transform newRoot, Selectable first)
    {
        currentUIRoot = newRoot;
        current = first;
        EventSystem.current.SetSelectedGameObject(current.gameObject);
    }
}

SetUIFocus.cs

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

public class SetUIFocus : MonoBehaviour
{
    public Selectable popupFirstButton;
    public Transform popupCanvas;


    public Selectable backgroundLastButton;
    public Transform backgroundCanvas;
    void OnEnable()
    {
        // remote 是挂脚本的对象
        RemoteControlNavigation.Instance.SetUIRoot(popupCanvas.transform, popupFirstButton);

    }
    private void OnDisable()
    {
        RemoteControlNavigation.Instance.SetUIRoot(backgroundCanvas.transform, backgroundLastButton);

    }
}

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
AI助手
您好!我是硅基流动AI助手,请问有什么可以帮您的吗?