首页 > 解决方案 > 使用 EventSystem 进行按键事件

问题描述

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

void Update(){
    if (Input.GetKeyDown("W"))
        DoSomething();
}

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

标签: c#unity3d

解决方案


有没有办法使用 Unity 的 EventSystem 执行以下操作?换句话说,有没有像 IPointerClickHandler 这样的接口的实现,

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

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

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

void OnGUI()
{
    if (Event.current.Equals(Event.KeyboardEvent("W")))
    {
        print("W pressed!");
    }
}

这比在函数中使用Input.GetKeyDown函数更糟糕Update。我鼓励你坚持下去Input.GetKeyDown。没有什么问题。


如果您正在寻找没有输入系统的事件类型,请使用UnityInput.GetKeyDown的新输入 API 并订阅该InputSystem.onEvent事件。

如果您正在寻找类似于IPointerClickHandler接口的功能,您可以在Input.GetKeyDown.

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

2、创建一个界面“IKeyboardEvent”,并在界面中添加OnKeyDown类似OnPointerClickIPointerClickHandler功能。

3 . 遍历KeyCodefrom #1并检查数组中的每个键是否被按下、释放或按住。

4、获取场景中的所有组件,查看是否实现了IKeyboardEvent接口。如果是这样,请根据#3中的键状态在界面中调用适当的函数。

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

附加到一个空的游戏对象。

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);
}

用法

在脚本中实现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);
    }
}

推荐阅读