[Need Help] Raw Input Data As Events

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!

from how you’ve explained it, aren’t you just re-implementing the built in unity input manager?

if so, what functionality are you trying to add?

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.

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

Dictionary<KeyCode, Action> actions;

KeyCode[] presses = Input.GetKeyPresses();
foreach (var p in presses)
{
    Action a;
    if (actions.TryGetValue(p, out a)) a();
}

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? :slight_smile:

1 Like

Yeah, something like this indeed.
As for my signature, maybe I should revise it. It’s just that I help sometimes and I keep repeating “Don’t take my word for granted, since I am not a pro”, so I’ve put it in a permanent place :slight_smile:
I’ve found a RawInput API someone has made, I am not trying to decipher it and learn from it.

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 :stuck_out_tongue:

Even better would be the ability to hook a key press right in Input

Input.HookKeyPress(KeyCode.A, () => { Debug.Log("You pressed A!"); });

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.

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 :frowning:

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

public class DelegatedInput : MonoBehaviour
{
    DelegatedInput instance;
    public DelegatedInput Instance
    {
        get
        {
            if (instance == null)
            {
                var go = new GameObject("DelegatedInput");
                instance = go.AddComponent<DelegatedInput>();
            }
            return instance;
        }
       
        Dictionary<KeyCode, Action<KeyCode>> actions = new Dictionary<KeyCode, Action<KeyCode>>();
        List<KeyCode> listenerKeys = new List<KeyCode>();
       
        public void RegisterDelegate(KeyCode keyCode, Action<KeyCode> action)
        {
            if (actions.ContainsKey(keyCode))
            {
                actions[keyCode] += action;
            }
            else
            {
                actions[keyCode] = action;
                listenerKeys.Add(keyCode);
            }
        }
       
        void Update()
        {
            for (int i = 0; i < listenerKeys.Count; i++)
            {
                if (Input.GetKeyDown(listenerKeys[i])
                {
                    actions[listenerKeys[i]](listenerKeys[i]);
                }
            }
        }
    }
}
DelegatedInput.Instance.RegisterDelegate(KeyCode.A, (kc) => { Debug.Log(kc + " was pressed"); });

I think you could make what you are looking for with a combination of the Unity class Event and a Dictionary<HashSet, Action>

Event: Unity - Scripting API: Event
KeyCode: Unity - Scripting API: Event.keyCode
Dictionary: Dictionary<TKey,TValue> Class (System.Collections.Generic) | Microsoft Learn
HashSet: HashSet<T> Class (System.Collections.Generic) | Microsoft Learn
Action: Action Delegate (System) | Microsoft Learn