Looking for advice: managing input based on states

Hello,

I am planning out how to manage input. Currently, my player controller handles input and then calls functiosn on the player pawn or widgets directly. This could be replaced with interface calls but for the moment i see no problem with direct communications.

There are a few states in which input bindings have different effect and may speak to different actors.

I think the appropriate design here is something like a state machine. I can use an enumerator to name the states, and when an input is fired, check the enum and a switch will call appropriate actors.

For instance, if we are in the Quick Menu state (a certain widget is active), then WASD wont make the player pawn move, but instead call some other widgets, and so on.

Probably this graph explains easier than words:

I just wanted to see if anybody in the community has done something similar to this? Any problems I might not be aware of? Any simpler way to handle this?

My goal is for it to not be a hard-to-manage jumble of caveats. From what I understand, using a state machine pattern like this should mean that when i need to make changes in the future, each state is self-contained and if i am doing communications through an interface, then add/remove some states or changing logic that happens within a state shouldn’t break the whole system.

Thanks for any advice.

1 Like

Hey @BIGTIMEMASTER! State machines are a great way to control your different control schemes. To use them outside of the animator, you are going to have to use flow control nodes. For example, you can attach all of your states to booleans that while true use the “WhileLoop” and when false, return to the default state. Here is a good example video on the concept of setting something like that up.

3 Likes

thanks!

1 Like

So, that video gave me what I needed to solve my problems. I just want to make a quick summary for anybody in future with similar issues:

In the video he shows three ways to handle states:

  1. you just have a haywire of blueprints with lots of branches. This is probably what your code looks like when you are just figuring things out. This is also what blueprint code usually looks like in most tutorials you’ll find. It technically works, however its a nightmare to maintain or extend.

  2. Use enumerators and switches to control execution flow based on state. This is a little better, but as your code grows in complexity this can be hard to maintain. Too many moving pieces spread all over the place. This is where I was at the time I brought this question up - I was getting things to work, but it felt like there must be a better way.

  3. Lastly, the best solution - it seems complicated at first but after a little practice I realized its super easy to handle and make changes too. This is the method where we make Object classes for each state. This way, you have broken states into separate chunks so you know everything about a state is in this one place. No hunting around.

It’s one of those things when you read about it sounds confusing as hell but seeing it put into practice is easy to understand. So if you are curious just watch the video and spend a few hours practicing. Well worth it - now what would have been overly complicated has been simplified significantly.

Quick example of some testing I was doing:

So the State Object I am toggling on a key press. If it is set to null then my WASD keys operate character control normally. If another state is constructed then the input gets fed into the object. Then I can process what to do with the input however I want.


(i suppose you could have functions for each key mapping. But this works.)

I also fed in HUD widget and other stuff so that I can basically run whatever operations I want. Of course you can send interface calls and event dispatches as well.

And I also tested logic for changing to further states from within a state and that is all straightforward. This has made it possible to have a complex contextual UI menu that reuses input keys and communicates with many actors - all while having very little drain on my brain.

Okay, well this is answered. Thank you!

Summary

:thinking: ^This^ seems a bit of a horror show to me. :stuck_out_tongue_winking_eye: No seriously, you seem happy with this, so its all good. I’ll just mention something on the side. If you’re an Indie there is an easier way to do this maybe. Just embed the inputs / states inside the pawn. Since the pawn knows everything it needs to know about its own capabilities / states, its the best one to drive / manage all this.

That way the player can also control lots of different pawns or drive lots of different vehicles, or operate lots of different machinery / puzzles / hacks. And yet - you don’t have to worry about all the different states or state management. I used to spend too long merging Marketplace pack Characters / Pawns, it was seriously unproductive (lots of overhead / overkill debugging).

My games are mostly 30 min repeat open-world gameplay where there’s lots of different things to do all the time. If I had to manage / troubleshoot that with state objects I’d be reaching for :gun:. :grin:

But hey there were a lot of interesting threads about this maybe 5 years ago when the forums were actually worth a sht. It was interesting to note then that devs like TheJamsh argued for PAWN vs PC for handling inputs iirc. But hey whatever works for you is all that counts, especially in Indie dev. Pro-Devs working in pro-environments have lots of other things to worry about. :wink:

1 Like

yeah i can see how that makes sense for managing different actors. But then you have to micromanage who gets input priority?

In my case, there is only one actor, just depending on what layer of UI menus you are in, the WASD and a few other keys should do different things. So using the object states like this means I just have a single place I can go to do everything necessary for “menu A is on” state, rather than having a million switches and branches and flags to keep track of.

I wasnt on these forums back in the glory days, but it seems like such is the case for most the forums I frequent. A golden era from around 2014-2016 and tapering off after there. I wonder why. I guess most people are on discord or similar. I find live chat to be too distracting. Anywho, at least forums are easy to search!

For sure… But then you’re into the whole other world of hurt namely, how do you design the ****** UI anyway? :stuck_out_tongue: For example, do you want to make the UI as diegetic as possible (think FarCry2). There’s lots of Indies on here who are fans of that approach. As the game world feels more immediate / interactive and less modal menu driven or a bit bland, plus a localization nightmare.

If so, then everything is an-world widget (possibly using the WIC) or even RTT. You then embed the logic into the widget or rtt actors. Each one checks if is Visible or Exists. If so, it in-turn can relay inputs to whoever needs them via interface calls. So you’re still embedding game logic / state into Sub-Actors / Sub-BP’s. This can actually be a real time saver when the game evolves or develops new features, as its much easier to isolate problem sections (new features added).

So ‘on’ just means something is visible / exists, and you know which mode / state you’re in, both in-code and on-screen. :wink: One of things that’s nice about game dev in general is how visual it is. Even if you need to show a mode change that doesn’t have a widget, you can alter a bar of material on the player’s arm for example, and then that’s the current mode. So extra variables aren’t even needed. Simplicity is key so as gameplay evolves you don’t keep breaking things. :blush:

I think i understand what you mean sort of. But in my case, this is 99% for getting around through UI menus.

Think like a radial menu, where each pie element is bound to a hotkey, and you can drill down into deeper menus just reusing those same WASD keys each time. And then one universal cancel all key will return back to regular input mode button.

This use of object classes has made it a lot simpler. Before I had huge graphs with all these complex conditions - very hard to manage and debug. Now its just like tossing things in a bucket.

This UI state? It gets mouse control, W key does this. Doesnt do anything with D key.
That UI state? No need for mouse control, A does this, etc.

I initially went for a diegetic approach with this game but that made it too hard in some cases. And also there was too many keys. So mostly I am trying to keep it as minimal keys as possible, which is a challenge given that it’s a simulation game with unique input needs (in other words, I cant jsut copy standard shooter templates).

Its working… So stick with what you have for sure. But if at all anytime in the future maintenance starts to eat away at your time or becomes a PITA (weight of new features added that you couldn’t account for at the time), then maybe take a step back. But if not then its happy days. :+1: