当我按下与该脚本无关的键盘按键时,Unity 按钮脚本就会运行

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

我是 Unity 的新手,我的应用程序遇到了一些奇怪的问题。该程序是一个数字屏幕键盘,单击时显示按下的数字值,并在按下 Enter 按钮时将其发送到另一个函数(参见屏幕截图 1)。

app

到目前为止,一切都是正确的,但为了让用户能够使用数字物理键盘输入和发送数字,相同的逻辑已应用于物理数字键(参见屏幕截图 2 和 3)。

logic implemented for keyboard keys 1

logic implemented for keyboard keys 2

问题是,当我在使用屏幕键盘后使用物理键盘并按下键盘的 Enter 键时,它还会运行附加到屏幕键盘上单击的最后一个按钮的脚本。

这是附加到按钮编号的脚本(屏幕截图 4)。

script attached to button numbers

输入按钮只需运行与第三个屏幕截图中相同的函数:GetAnswer()

我省略了我认为(希望)不相关的代码的其他部分。

总结一下,我尝试了两种提交数字的方法,但是当我将它们组合起来时,它无法正常工作。按下 Enter 键盘键时,按钮脚本也会运行,但按下其他键盘键时不会运行。

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

正如 BugFinder 在评论中指出的那样:Unity UI 有一个 focus / 选定的对象。

您基本上可以将其想象为一个 Web 界面,您可以使用选项卡按钮来选择不同的 UI 元素。

当您在 UI.Button 仍处于选中状态时按下

Enter
时,Unity 会将其视为提交,并且会再次单击该按钮。


如上所述,为了在一个地方解决这个问题,我首先要有一个控制文本的中央控制器:

// TODO: find a better name
public class Controller : MonoBehaviour
{
    [SerializeField] private TMP_Text displayText;

    public void AppendValue(int value)
    {
        displayText.text += value.ToString();

        // make sure buttons are not selected anymore after clicking
        EventSystem.current.SetSelectedGameObject(null);
    }

    public int GetAndResetValue()
    {
        var value = int.Parse(displayText.text);

        ResetValue();

        return value;
    }

    public void ResetValue()
    {
        displayText.text = string.Empty;

        // make sure also the enter button isn't selected to avoid handling the event twice
        EventSystem.current.SetSelectedGameObject(null);
    }
}

这样您只需在一个地方实现和维护它

然后你可以在你的按钮中使用它

public class GetNumber : MonoBehaviour
{
    [SerializeField] private Controller controller;

    private int value;

    private void Start()
    {
        value = int.Parse(GetComponentInChildren<TMP_Text>().text);
    }

    public void getNumber()
    {
        controller.AppendValue(value);
    } 
}

和其他基于键盘的输入相同

[SerializeField] private Controller controller;

....
if(Input.GetKeyDown(KeyCode.KeyPad0))
{
    controller.AppendValue(0);
}
....

private void GetAnswer()
{
    var answer = controller.GetAndResetValue;
    
    // do something with answer
}

private void Erase()
{
    controller.ResetValue();
}
© www.soinside.com 2019 - 2024. All rights reserved.