使用EventSystem进行按键事件

7 c# unity-game-engine

上下文:假设您正在检查键盘上是否按下了"W",最常见的检查方法是通过以下代码:

void Update(){
    if (Input.GetKeyDown("W"))
        DoSomething();
}
Run Code Online (Sandbox Code Playgroud)

有没有办法使用Unity的EventSystem执行以下操作?换句话说,是否有像IPointerClickHandler这样的接口的实现,例如,检查按钮是否被按下,而不是在Update()函数中这样做?

Pro*_*mer 7

有没有办法使用Unity的EventSystem执行以下操作?换句话说,是否有IPointerClickHandler之类的接口的实现,

否。EventSystem主要用于光线广播和调度事件。这不用于检测键盘事件。EventSystem中唯一可以检测键盘事件的InputField组件是该组件。就是这样,它不能用于其他任何用途。

检查是否按下了按钮,而没有在Update()函数中这样做?

是的,有一种方法,Event.KeyboardEvent这需要OnGUI功能。

void OnGUI()
{
    if (Event.current.Equals(Event.KeyboardEvent("W")))
    {
        print("W pressed!");
    }
}
Run Code Online (Sandbox Code Playgroud)

这比将Input.GetKeyDown功能与功能一起使用更糟糕Update。我鼓励你坚持Input.GetKeyDown。没有什么问题。


如果要查找事件类型InputSystem,而无需,Input.GetKeyDown则使用Unity的新Input API并订阅InputSystem.onEvent事件。

如果您正在寻找与IPointerClickHandler接口类似的功能,则可以在之上实现它Input.GetKeyDown

1。首先,获取所有KeyCode枚举System.Enum.GetValues(typeof(KeyCode));并将其存储在数组中。

2。创建一个接口“ IKeyboardEvent”,并添加诸如该接口之OnKeyDownOnPointerClickIPointerClickHandler功能。

3。KeyCode#1循环浏览,并检查是否按下,释放或按住阵列中的每个键。

4。获取场景中的所有组件,并检查它们是否实现了IKeyboardEvent接口。如果是这样,则根据#3中的键状态在界面中调用适当的功能。

这是一个仍可以扩展或改进的功能示例:

附加到一个空的GameObject。

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class KeyboardEventSystem : MonoBehaviour
{
    Array allKeyCodes;

    private static List<Transform> allTransforms = new List<Transform>();
    private static List<GameObject> rootGameObjects = new List<GameObject>();

    void Awake()
    {
        allKeyCodes = System.Enum.GetValues(typeof(KeyCode));
    }

    void Update()
    {
        //Loop over all the keycodes
        foreach (KeyCode tempKey in allKeyCodes)
        {
            //Send event to key down
            if (Input.GetKeyDown(tempKey))
                senEvent(tempKey, KeybrdEventType.keyDown);

            //Send event to key up
            if (Input.GetKeyUp(tempKey))
                senEvent(tempKey, KeybrdEventType.KeyUp);

            //Send event to while key is held down
            if (Input.GetKey(tempKey))
                senEvent(tempKey, KeybrdEventType.down);

        }
    }


    void senEvent(KeyCode keycode, KeybrdEventType evType)
    {
        GetAllRootObject();
        GetAllComponents();

        //Loop over all the interfaces and callthe appropriate function
        for (int i = 0; i < allTransforms.Count; i++)
        {
            GameObject obj = allTransforms[i].gameObject;

            //Invoke the appropriate interface function if not null
            IKeyboardEvent itfc = obj.GetComponent<IKeyboardEvent>();
            if (itfc != null)
            {
                if (evType == KeybrdEventType.keyDown)
                    itfc.OnKeyDown(keycode);
                if (evType == KeybrdEventType.KeyUp)
                    itfc.OnKeyUP(keycode);
                if (evType == KeybrdEventType.down)
                    itfc.OnKey(keycode);
            }
        }
    }

    private static void GetAllRootObject()
    {
        rootGameObjects.Clear();

        Scene activeScene = SceneManager.GetActiveScene();
        activeScene.GetRootGameObjects(rootGameObjects);
    }


    private static void GetAllComponents()
    {
        allTransforms.Clear();

        for (int i = 0; i < rootGameObjects.Count; ++i)
        {
            GameObject obj = rootGameObjects[i];

            //Get all child Transforms attached to this GameObject
            obj.GetComponentsInChildren<Transform>(true, allTransforms);
        }
    }

}

public enum KeybrdEventType
{
    keyDown,
    KeyUp,
    down
}

public interface IKeyboardEvent
{
    void OnKeyDown(KeyCode keycode);
    void OnKeyUP(KeyCode keycode);
    void OnKey(KeyCode keycode);
}
Run Code Online (Sandbox Code Playgroud)

用法

IKeyboardEvent就像使用一样,可以在脚本中实现接口及其功能IPointerClickHandler

public class test : MonoBehaviour, IKeyboardEvent
{
    public void OnKey(KeyCode keycode)
    {
        Debug.Log("Key held down: " + keycode);
    }

    public void OnKeyDown(KeyCode keycode)
    {
        Debug.Log("Key pressed: " + keycode);
    }

    public void OnKeyUP(KeyCode keycode)
    {
        Debug.Log("Key released: " + keycode);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • “我鼓励您坚持使用Input.GetKeyDown。它没有任何问题。” 但事件驱动的驱动(可能由键盘驱动程序级别密切驱动)会更好。更好的是它是中断驱动而不是轮询。唉,你说过 Unity 中不存在这种情况。 (3认同)