Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

[Need Help] Raw Input Data As Events

Discussion in 'Scripting' started by MrPriest, Sep 21, 2015.

  1. MrPriest

    MrPriest

    Joined:
    Mar 17, 2014
    Posts:
    202
    Hello everyone.
    First of all, I want to make it known that I am not looking for an answer, but a direction, I want to reach the answer myself.

    Now for the issue at hand;
    I want to create an input manager.
    I've practically made it already, a manager that holds the keys, during update if a key that is set (be it at runtime from a menu, or hardcoded\defaulty set by the dev) is pressed, it will call the execution of the assigned action.
    Furthermore, an action can be assigned multiple keys for combo actions.

    So basically...
    The end result is this workflow;
    User has the "Jump" action.
    User selects it to change key configuration, and the input menu awaits a key input.
    User presses any key.
    A code\signal is transmitted from the input device, be it "w", "0x234" or whatever, it does not matter what the key itself is, rather which key signal it emits. As such, it would not matter if you use English or German with your keyboard, or if it was a mouse or a controller.
    The key class assigns the signal to listen to, and during gameplay, when the signal is received, it activates its own action.

    Is this possible?

    Is there a way to listen to raw input data and wait for it using listeners (NOT using monobehaviour and update)?
    I figured trying using User32.dll (at least for windows platform) but I'd rather like to use something more generic (rather than specific windows key signals, raw input signals).

    I am aware that I am not that well versed at explaining myself, so if you need any further input, please do not hesitate to ask.

    Thank you for your time!
     
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
  3. MrPriest

    MrPriest

    Joined:
    Mar 17, 2014
    Posts:
    202
    Well, I am implementing an input manager, true.
    However the way I want to implement it, is having the keypress call an action, not MonoBehaviour ask if a key was pressed every frame.

    I'll give an example of both;

    Jump = X button
    Attack = A button

    Using Input Manager:
    Frame 1:
    Is X pressed?
    Is A pressed?
    Frame 2:
    Is X pressed?
    Is A pressed?
    etc...

    Using what I want:
    Frame 1:

    User pressed X
    Frame 2:
    Jump class listening to X key executes

    Basically, I want to separate Input management from action code.
     
  4. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    For years I've wanted a way to get all the key presses for a given frame to do just this. Some of the Event stuff exposed in OnGUI can get you close but it'd be really nice to have something like
    Code (csharp):
    1.  
    2. Dictionary<KeyCode, Action> actions;
    3.  
    4. KeyCode[] presses = Input.GetKeyPresses();
    5. foreach (var p in presses)
    6. {
    7.     Action a;
    8.     if (actions.TryGetValue(p, out a)) a();
    9. }
    10.  
    Offtopic - your signature is rather off-putting. If you don't have the time (or the will) to use Unity then why are you here in the first place? :)
     
    MrPriest likes this.
  5. MrPriest

    MrPriest

    Joined:
    Mar 17, 2014
    Posts:
    202
  6. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    I always thought the point of the built in input manager was to say

    button x, y and z are referred to as "jump"

    so you could use

    Input.GetButton("jump")

    rather than referencing the specific key, you can then simply have one loop checking each defined input reference calling the specific action it applies to.


    I get what you're saying though, that would be a few more hoops to jump through than what you're looking for, but as Kelso points out there isn't a way to get all the current keys (which would be soooo useful!)


    <== still a newbie :p
     
  7. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Even better would be the ability to hook a key press right in Input
    Code (csharp):
    1.  
    2. Input.HookKeyPress(KeyCode.A, () => { Debug.Log("You pressed A!"); });
    3.  
     
  8. MrPriest

    MrPriest

    Joined:
    Mar 17, 2014
    Posts:
    202
    Yeah, that's what I meant by events instead of update.
    But I'll give it up for now, I am not that good with that kind of low-level (or is it high level?) code.
     
  9. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    What's sorely missing from Unitys new InputManager are "fallthrough" events. I wanted to detect a drag anywhere onscreen, even if not "dragging" on a collider in order to control a camera movement. I had to write my own manager which polls input again just to send generic events. I felt quite dirty doing it and couldn't find anyone who had a similar problem. I previously used nGUI which had this functionality :(
     
  10. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Our RTS camera sort of does that. It tracks pointer location on right click down and measures "drag" distance from that point to determine camera move direction and move speed (the farther you move your cursor the faster the camera moves).

    Rolling your own input system like that wouldn't be terrible - but you'd still be monitoring Input.GetKey in an Update somewhere. Still might be nice though. Something like this

    Code (csharp):
    1.  
    2. public class DelegatedInput : MonoBehaviour
    3. {
    4.     DelegatedInput instance;
    5.     public DelegatedInput Instance
    6.     {
    7.         get
    8.         {
    9.             if (instance == null)
    10.             {
    11.                 var go = new GameObject("DelegatedInput");
    12.                 instance = go.AddComponent<DelegatedInput>();
    13.             }
    14.             return instance;
    15.         }
    16.        
    17.         Dictionary<KeyCode, Action<KeyCode>> actions = new Dictionary<KeyCode, Action<KeyCode>>();
    18.         List<KeyCode> listenerKeys = new List<KeyCode>();
    19.        
    20.         public void RegisterDelegate(KeyCode keyCode, Action<KeyCode> action)
    21.         {
    22.             if (actions.ContainsKey(keyCode))
    23.             {
    24.                 actions[keyCode] += action;
    25.             }
    26.             else
    27.             {
    28.                 actions[keyCode] = action;
    29.                 listenerKeys.Add(keyCode);
    30.             }
    31.         }
    32.        
    33.         void Update()
    34.         {
    35.             for (int i = 0; i < listenerKeys.Count; i++)
    36.             {
    37.                 if (Input.GetKeyDown(listenerKeys[i])
    38.                 {
    39.                     actions[listenerKeys[i]](listenerKeys[i]);
    40.                 }
    41.             }
    42.         }
    43.     }
    44. }
    45.  
    Code (csharp):
    1.  
    2. DelegatedInput.Instance.RegisterDelegate(KeyCode.A, (kc) => { Debug.Log(kc + " was pressed"); });
    3.  
     
  11. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971