Use EventSystem for key-pressing events

前端 未结 2 1416
礼貌的吻别
礼貌的吻别 2021-01-12 06:02

Context: say you\'re checking whether \"W\" is pressed on the keyboard, the most common way to check this is through the following code:

void Update(){
    i         


        
相关标签:
2条回答
  • 2021-01-12 06:28

    Is there a way to do the following, using Unity's EventSystem? In other words, is there an implementation of an interface like IPointerClickHandler,

    No. The EventSystem is mostly used for raycasting and dispatching events. This is not used to detect keyboard events. The only component from the EventSystem that can detect keyboard events is the InputField component. That's it and it can't be used for anything else.

    Check whether a button is pressed, without doing so in an Update() function?

    Yes, there is a way with Event.KeyboardEvent and this requires the OnGUI function.

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

    This is worse than using the Input.GetKeyDown function with the Update function. I encourage you to stick with Input.GetKeyDown. There is nothing wrong with it.


    If you are looking for event type InputSystem without Input.GetKeyDown then use Unity's new Input API and subscribe to the InputSystem.onEvent event.

    If you are looking for feature similar to the IPointerClickHandler interface you can implement it on top of Input.GetKeyDown.

    1.First, get all the KeyCode enum with System.Enum.GetValues(typeof(KeyCode)); and store it in an array.

    2.Create an interface "IKeyboardEvent" and add functions such as OnKeyDown just like OnPointerClick in the IPointerClickHandler interface.

    3.Loop through the KeyCode from #1 and check if each key in the array is pressed, released or held down.

    4.Get all the components in the scene and check if they implemented the IKeyboardEvent interface. If they do, invoke the proper function in the interface based on the key status from #3.

    Here is a functional example that can still be extended or improved:

    Attach to an empty 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);
    }
    

    Usage:

    Implement the IKeyboardEvent interface and the functions from it in your script just like you would with 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);
        }
    }
    
    0 讨论(0)
  • 2021-01-12 06:43

    I created an simples script to trigger simple event. I used OnguiGUI instead of Update. See it bellow!

    using UnityEngine;
    using UnityEngine.Events;
    
    public class TriggerKey : MonoBehaviour
    {
    
        [Header("----Add key to trigger on pressed----")]
        public string key;
    
        // Unity event inspector
        public UnityEvent OnTriggerKey;
    
        public void OnGUI()
        {    // triiger event on trigger key
            if (Event.current.Equals(Event.KeyboardEvent(key)))
            {
                OnTriggerKey.Invoke();
                print("test trigger btn");
            }
    
        }
    }
    
    0 讨论(0)
提交回复
热议问题