Используйте EventSystem для событий нажатия клавиш - PullRequest
0 голосов
/ 22 мая 2018

Контекст: скажем, вы проверяете, нажата ли клавиша "W" на клавиатуре, наиболее распространенный способ проверить это с помощью следующего кода:

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

Есть ли способ сделать следующее, используя систему событий Unity?Другими словами, существует ли реализация интерфейса, подобного IPointerClickHandler , например, для проверки, нажата ли кнопка, без этого в функции Update () ?

1 Ответ

0 голосов
/ 22 мая 2018

Есть ли способ сделать следующее, используя систему событий Unity?Другими словами, есть ли реализация интерфейса, такого как 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.В этом нет ничего плохого.


Если вы ищете тип события InputSystem без Input.GetKeyDown, используйте новый API ввода Unity и подпишитесь на событие InputSystem.onEvent.

Если вам нужна функция, аналогичная интерфейсу IPointerClickHandler, вы можете реализовать ее поверх Input.GetKeyDown.

1 . Во-первых, получите все KeyCode перечислите System.Enum.GetValues(typeof(KeyCode)); и сохраните его в массиве.

2 . Создайте интерфейс "IKeyboardEvent" и добавьте такие функции, как OnKeyDown, как OnPointerClick, в IPointerClickHandler interface.

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

Использование :

Реализация интерфейса 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...