Redirecting generic input to ActorComponents

I have a need to be able to redirect input to a pluggable ActorComponents. The idea is that each ActorComponent will handle its own unique input evens (either classic of Enhanced) so I can’t just put them (input actions) on actor and redirect, it would defeat the point of having a pluggable AC with unique logic to begin with. Now, I could theoretically poll PlayerController on an EvenTick in the Component and switch on current key input event via PC instance, the issue is that the moment game is paused or PController input set to disabled - this input stream dies and I need it working always, as long as component’s Actor alive and active. And I’m limited to real of BP, however, I can expose any existing function, already marked as UFUNCTION, in the Engine, if needed.

Any ideas?

Have the PC tell the actor to look up a component with an interface and send a message. Wouldn’t that work?

Input in the PC:

image

PC is not part of the equation, Actor that owns component is a standalone thing.
And In what way interface will help? This means I have to pre-define each Input Action on the Actor, parent of specific impl, does not matter. The logic of a component leaks into Actor + if I make new component that does absolutely different thing, new actions have to be added to an Actor so it can route them (or if I scrap and delete 2-3 components I now have to remember which actions are outdated) As I mentioned before, I can’t rely on polling PC, because it stops sending input events when it has input disabled or game is paused.

As far as I know there is no way to send just over generic input event.

Where do you handle input then?

And In what way interface will help?

It renders communication type agnostic. You send messages to a component and they decide themselves whether they want to process this generic input, regardless of its source.

Here’s what I mean:

  • actor with components receiving input however you need:

  • base class of the component:

Children comps override the interface implementation if needed.

Actor can auto-receive input from LocalPlayer #. PC not particularly relevant here, even if disable input on PC, Actor still will receivine its own input action (but ONLY as properly defined Input action, classic or Enhanced does not matter).

Again, how do you see interface working? Say, Component 1 uses Classic Input and has 2 Axis mappings (WASD) and 3 ActionMappings; Ctrl+P, Alt+Shift+R and F1.
Component 2 also uses Classic Input and has its own custom Action Mappings.
How do you propose sending correct events to said actors WITHOUT the logic of said input leaking owning Actor? Because Actor WILL NEED to know about such actions to send them (they can be rebound hence why they are Axis/Action mappings), which defeats the point of unique isolated logic.

Again, how do you plan to handle specific rebindable AxisAction Mapping, though, or EI InputAction?
Right, we put them on an Actor… which renders logic isolation through Components useless. It violates the idea of composition. And then when I add component4, the owning Actor will need to know its specific bindings and so on.

This is precisely the question at hand. I wish it was so easy as some interface.

I wasn’t, you did not mention it until now.

Fair enough but then again, if Input was fixed there would be no question in a first place :stuck_out_tongue:

I admit I do not fully understand what you’re trying to achieve (or why). Regarding the above, query the actor for its components so you can send them messages directly. The owning actor does not need to propagate anything.

Something along the lines of:

The interface may or may not be necessary, inheritance may suffice. Too many unknowns.


Perhaps you could rephrase the original post and include more gotchas? There is, ofc, a chance you’ve reached what BPs input & comms, enhanced or otherwise, can achieve.


or why

Quite curious, though. :innocent:

Imagne you have an ActionMapping:

+ActionMappings=(ActionName="TestMode",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftShift)

It can be bound/rebound at runtime, which is why it is abstracted by Input system as an action “TestMode”.
Cool. This action “TestMode” (as well as 5 others, for example) is ONLY RELEVANT to type of Component2. Only that instance processes it. So, Actor spawns, reads config, and plugs in current component (there is only one, they are just swapped when/if needed) it works with - Component2. Now, how can said component receive “TestMode” input(which could be rebound now)? Of course, we can just put it on an owning Actor and send to the Component, via interface or whatever… except now it is Actor that handles Component-specific logic (as well), it is no longer isolated to the component.
Okay, how about instead we just poll input in EvenTick on Component? Well, we could do that, but the moment game isPaused or PC input is disabled, Component’s input polling on Tick is useless, because it can no longer receive inputs from PC (and polling directly on tick is possible only via PC, sadly).

Okay, how about instead we put EVER SINGLE ONE keyboard and gamed input on Actor and just redirect all events via interface? That could work, except for complex inputs like Ctrl+Shift+P, we no longer have a deterministic consistency (“eventual input consistency” (c)), we can receive even P before receiving event Shift and so our logic is faulty/unreliable. And this is just beside the fact whole thing will look like pure trash.

Does this illustrate the issue I’m trying to solve? Whole architecture dies because of simple input redirect and components, sadly, NEED to handle unique input actions each.

After some thinking, I’ve settled on this approach. Owning Actor will have its own input stack it will use to compose input combo structs. It will monitor AnyInput IA and add new pressed key to the stack and then immediately compose the binding out of up-to-date stack state and send it to the Component as a binding, which it will use to compare against its map of inputs.
This is horribly inefficient and extremely bad performance wise , because it is done in BP VM, but to alleviate this issue I’ve added a state flag that will skip any input processing when Actor/component functionality is not needed. This is less flexible than I imagined in my perfect fluffy world, but it will do. At the very least, it gives me ability to use rebinding still.

I’m marking this a solution, even though it isnt really one.
To anyone who will encounter this in a future: REMEMBER, I’m limited to BP realm only in my very specific context. If you have access to C++, for the love of the god, just use InputComponent(s) directly.

1 Like