Unity 3D IMGUI 控件,Gui。按钮选择/主动使用键盘

问题描述 投票:0回答:1

对于Unity3D 或需要使用旧的OnGui/Gui.Button。

对于旧项目,我无法使用新的 UI,因为它需要转换整个项目。 我无法解决的问题,我在网上到处搜索信息,但找不到任何清晰且简单的解决方案来解决我的问题。 或者需要使用键盘按键选择 Gui.Button: A / S 或向上箭头/向下箭头滚动/选择所有单个 GUI 按钮。

就像您将鼠标悬停在其上一样。 我设法找到一个简单的解决方案来模拟使用键盘上的 A 键单击鼠标,是否有一个同样简单的解决方案可以做到这一点? 我谢谢

void OnGUI () {

if (GUI.Button(new Rect(25,25,100,30),Button")||Input.GetKeyUp(KeyCode.A)){

|| Input.GetKeyUp (KeyCode.A)){//this active :click :在这里输入输入键将通过添加 Up 而不是 Down 来完美模拟单帧按键。

但是对于选择单个GUI,按钮使用键盘按键?

使用按键模拟选择鼠标单GUI。按钮?

示例: 按 A/向下箭头键 = 选择:

1-桂。按钮(“开始游戏”)

按 A/向下箭头键 = 选择:

2-桂。按钮(“选项”)

按 A/向下箭头键 = 选择:

3-桂。按钮(“退出游戏”)


按 S/向上箭头键 = 选择:

1-桂。按钮(“退出游戏”)

按 S/向上箭头键 = 选择:

2-桂。按钮(“选项”)

按 S/向上箭头键 = 选择:

3-桂。按钮(“开始游戏”)

c# unity-game-engine user-interface button
1个回答
0
投票

如果我理解正确的话,您想要的是选择并浏览类似于在浏览器中使用 TAB 键的控件。

正如您所说,使用内置此功能的 UI 系统非常简单。

仅使用

OnGUI
这可能有点复杂。它可以通过使用诸如
GUI.SetNextControlName
GUI.FocusControl
GUI.GetNameOfFocusedControl
Event.current
之类的东西来完成。

然后对于每个按钮,您需要

  • 定义唯一的名称/ID(例如标签)
  • 定义4个邻居,根据箭头键选择下一步

这是我粗略构建的一个示例来展示用法

public class Example : MonoBehaviour
{
    // info about which next UI to select when pressing arrow keys
    private class FocusInfo
    {
        public string Right {get;}
        public string Left { get;}
        public string Up { get;}
        public string Down { get;}

        public FocusInfo(string right, string left, string up, string down)
        {
            Right = right;
            Left = left;
            Up = up;
            Down = down;
        }
    }

    // info about which next UI to select when pressing arrow keys for each button
    private readonly Dictionary<string, FocusInfo> focusInfos = new Dictionary<string, FocusInfo>();

    // currently focused control
    // used to keep focus on the last focused control even if clicked somewhere else
    private string currentFocused;

    private void OnGUI()
    {
        DrawAndRegisterButton(new Rect(10, 10, 100, 30), "Top Left",()=>
        {
            Debug.Log("Top Left");
        }, "Top Center", null, null, "Middle Left");
    

        DrawAndRegisterButton(new Rect(Screen.width - 110, 10, 100, 30), "Top Right",()=>
        {
            Debug.Log("Top Right");
        }, null, "Top Center", null, "Middle Right");

        DrawAndRegisterButton(new Rect(10, Screen.height - 40, 100, 30), "Bottom Left",()=>
        {
            Debug.Log("Bottom Left");
        }, "Bottom Center", null, "Middle Left", null);

        DrawAndRegisterButton(new Rect(Screen.width - 110, Screen.height - 40, 100, 30), "Bottom Right",()=>
        {
            Debug.Log("Bottom Right");
        }, null, "Bottom Center", "Middle Right", null);

        DrawAndRegisterButton(new Rect(Screen.width / 2 - 50, 10, 100, 30), "Top Center",()=>
        {
            Debug.Log("Top Center");
        }, "Top Right", "Top Left", null, "Bottom Center");

        DrawAndRegisterButton(new Rect(Screen.width / 2 - 50, Screen.height - 40, 100, 30), "Bottom Center", ()=>
        {
            Debug.Log("Bottom Center");
        }, "Bottom Right", "Bottom Left", "Top Center", null);

        DrawAndRegisterButton(new Rect(10, Screen.height / 2 - 15, 100, 30), "Middle Left", ()=>
        {
            Debug.Log("Middle Left");
        }, "Middle Right", null, "Top Left", "Bottom Left");

        DrawAndRegisterButton(new Rect(Screen.width - 110, Screen.height / 2 - 15, 100, 30), "Middle Right", ()=>
        {
            Debug.Log("Middle Right");
        }, null, "Middle Left", "Top Right", "Bottom Right");

        HandleKeybord();

        InitializeOnceWithFocus("Top Left");
            
        KeepFocusOnCurrent();
    }

    // Simplify drawing and registering of buttons
    // Assuming for now that label = unique ID
    // Includes assigning name to each control so they can be focused later
    private void DrawAndRegisterButton( Rect rect, string label, Action onClick, string right, string left, string up, string down)
    {
        GUI.SetNextControlName(label);
        if (GUI.Button(rect, label))
        {
            onClick?.Invoke();
        }

        if(!focusInfos.ContainsKey(label))
        {
            focusInfos.Add(label,new FocusInfo(right, left, up, down));
        }
    }

    // At the beginning of the game, focuses the first button
    private void InitializeOnceWithFocus(string focus)
    {
        if (!string.IsNullOrWhiteSpace(currentFocused)) return;

        GUI.FocusControl(focus);
        currentFocused = focus;
    }

    // Handles the arrow keys and focuses the next UI
    private void HandleKeybord()
    {
        var e = Event.current;
        if(e.type != EventType.KeyDown) return;

        switch(e.keyCode)
        {
            case KeyCode.UpArrow:
            case KeyCode.DownArrow:
            case KeyCode.RightArrow:
            case KeyCode.LeftArrow:    
                FocusNext(e.keyCode);
                break;
        }
    }

    // Focuses the next UI based on the arrow key pressed
    private void FocusNext(KeyCode keyCode)
    {
        var current = GUI.GetNameOfFocusedControl();

        if(!focusInfos.TryGetValue(current, out var info)) return;
        
        var next = keyCode switch {
        
            KeyCode.UpArrow => info.Up,
            KeyCode.DownArrow => info.Down,
            KeyCode.RightArrow => info.Right,
            KeyCode.LeftArrow => info.Left,
            _ => null
        };

        if(!string.IsNullOrWhiteSpace(next))
        {
            currentFocused = next;
            GUI.FocusControl(next);
        }
    }

    // Maintains the focus on currentFocused if e.g. clicked anywhere 
    private void KeepFocusOnCurrent()
    {
        if(!focusInfos.ContainsKey(GUI.GetNameOfFocusedControl()))
        {
            GUI.FocusControl(currentFocused);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.