Binding multiple inputs to a single action mapping

Example use case:

There are 12 boxes in the scene, indexed 0 to 20. The user can press combinations of any of 0-9 to open each box at its index, ex. press 2 -> opens box at index 2. However, if the user say holds 2 instead of just tapping it, boxes[2] will float in the air, then drop back to the ground when the key is released.

Problem:

I don’t want to go through and create pressed/released/etc. function callbacks for all 10 digits. That would be 40 tiny functions for one simple action of selecting an index.

Attempted solutions:

  1. Binding all ten digits to one callback function. So whenever something happens with 0-9, the event will be handled with a general function like numberPressed(), numberReleased(), etc. Problem: I can’t find out exactly which number was pressed. Note that 0-9 may not be 0-9–the user can set it to A-G or whatever–so I can’t hard code a check for a specific number, either.
  2. Binding them to an axis input. I’ve been attempting to work with this for what must be two days now but there are so many parts of it that are making it nigh impossible–mainly how numbers can come in as an added value if they are held at the same time (ex. press 1 and 2, get 3 when it should mean 12). Not being able to know whether the number has just been pressed or released both fuels this problem as well as being a whole other thing of its own. I tried keeping track of the states manually, but it’s not as easy as predicted, what with the spaghetti values.

Is there another way of going about this? To iterate, I need to know what key was pressed and how it was pressed (tapped/held/released/double-tapped), and I would like to know this without making 40 functions that do the same thing.

I did previously ask this at the answer hub, but got no answers and very few views–numeric selection is a pretty core element in my game so I’m trying again here. Thanks for any help.

First of all, welcome to the forums.

Now I cannot directly answer your questions but only try to point you in the right direction. I am not familiar with the changes to the input system from UDK to UE4 but in UDK you could simply specify something like this in your

Where switchweapon would be the name of the function that is called and the number afterwards the argument passed to it. I would assume that a similar setup is still possible in UE4. In order to combine this with a “release” function you could modify it like this


.Bindings=(Name="GBA_SwitchWeapon1",Command="switchweapon 1 | OnRelease release 1")
.Bindings=(Name="GBA_SwitchWeapon2",Command="switchweapon 2 | OnRelease release 2")
.Bindings=(Name="GBA_SwitchWeapon3",Command="switchweapon 3 | OnRelease release 3")
.Bindings=(Name="GBA_SwitchWeapon4",Command="switchweapon 4 | OnRelease release 4")
.Bindings=(Name="GBA_SwitchWeapon5",Command="switchweapon 5 | OnRelease release 5")
.Bindings=(Name="GBA_SwitchWeapon6",Command="switchweapon 6 | OnRelease release 6")
.Bindings=(Name="GBA_SwitchWeapon7",Command="switchweapon 7 | OnRelease release 7")
.Bindings=(Name="GBA_SwitchWeapon8",Command="switchweapon 8 | OnRelease release 8")
.Bindings=(Name="GBA_SwitchWeapon9",Command="switchweapon 9 | OnRelease release 9")
.Bindings=(Name="GBA_SwitchWeapon10",Command="switchweapon 10 | OnRelease release 0")

The key is being held as long as switchweapon N has been called but relase N has not.

This way, you would still need to maintain your input configuration but only have to implement one function per event type (or less if you would include a second boolean argument that indicates whether the call originated from a key press or release).

Your axis idea could work as well but the value would need to be some kind of “bitfield” where key 1 is represented by 1, key 2 by 10, key 3 by 100 and so on so that you can “decode” the keys that are pressed. For example when adding 1 and 2 you would get 11. And 11 means 1 and 2 are pressed.

Another solution that as a user I would probably find more intuitive could be to simply allow the user to (double)click on the box they want to open with their mouse cursor. If the user presses the mouse while hovering over a box but does not release the button again you could make the box float. This is just a suggestion you may want to evaluate as I do not know whether you have other restrictions.

Thanks,

Unfortunately it’s not possible to pass an argument into a delegate in UE4, but your post led me to use those keywords as a search term and thanks to that I was finally able to find something similar to what I want: This question

It does seem kind of like a hacky thing to do to use templates as arguments but it’s the only thing that works it seems. A bit heavy on the setup side though (need to define 10 separate action mappings, need 40 lines to write [FONT=Courier New]BindAction(“0”, IE_Pressed, this, &MyClass::numberPressed<0>), but at least it’s not 40 functions).

I really wonder if a better way to accomplish this will be implemented in the future…

“God dammit there must be a better way” I keep telling myself but according to what UE4 Staff said, they don’t see a need for it. I don’t understand the reasoning, I feel the same way as sgp, I really hope there will be a better way to accomplish this in the future…

You could make your life easier with some macros, did some a year ago for a similar issue. Once I’m back home I’ll post a snippet.

Could you perhaps please still post this? It would be much appreciated. :slight_smile:

Would also love to see that snippet

You can use this https://forums.unrealengine.com/development-discussion/c-gameplay-programming/1745352-pass-a-value-through-bindaction
Although you will still have to do something like



InputComponent->BindAction<FCustomInputDelegate>("1", IE_Pressed, this, &AMyActor::NumKey, 1);
InputComponent->BindAction<FCustomInputDelegate>("2", IE_Pressed, this, &AMyActor::NumKey, 2);
InputComponent->BindAction<FCustomInputDelegate>("3", IE_Pressed, this, &AMyActor::NumKey, 3);
InputComponent->BindAction<FCustomInputDelegate>("3", IE_Pressed, this, &AMyActor::NumKey, 4);
//so on