Handling input across different monobehaviours in different states

Hello, I’ve been searching far and wide for a solution to my problem. I assumed since every game has some form of input handling that there would be tons of advice about it but so far I haven’t found anything that helps.

I need some way of managing who gets input at what time. For example, normally in my game the player will have the input for moving, interacting, opening the Inventory, etc… But at some points that input will need to be blocked. If the player is speaking with an NPC they shouldn’t be able to just walk away or press interact again to restart the interaction, ideally all the input should be blocked at that time. But at other times only some of the input should be blocked, or even some of the input should do something different entirely. Perhaps Escape is the key to open the menu, but that is only the case if there aren’t any other windows open (and if there are then they should be closed and require another press of the Escape key to open the menu).

The only solutions I’ve seen so far are people just saying to keep a boolean for isInMenu or isInteractingWithNpc but that is definitely not the best way at all and it is super difficult to expand upon when adding new scenarios where input is blocked either fully or partially.

1 Like

Then enlighten us with the best way…?

In fact, its a very common and correct way of handling things like this (though not the only way)

For example. My multiplayer hack n slash has a dungeon manager ui that open and blocks input via bIsBrowsingDungeonManager.

Its also very easy to call implement (what have you) through the use of a singleton

Each to their own.

You can have one InputManager, which would have a Stack. InputReceiver would be a base class that has a ProcessInput(KeyCode k) or something to that effect, and anything that can handle input (the player character, the NPC you interact with, etc) derives from this. The InputManager is the only class that directly uses Unity’s Input class at all; everything else only interacts through these other methods; in its Update, InputManager takes input and passes it through to the top item of the stack only.

So you’d have your player as the “bottom” of this, so if nothing else is open, it receives the input. If a menu is open, then push it onto the stack; now that’s the only thing that receives the input. When you close a menu, Pop it off the stack - if there’s another menu behind it, that will now receive the input, or if not it will fall back to the player.

1 Like

Sometimes it’s easy to imagine “Oh, this solution will lead to spaghetti code down the road” without being able to clearly see the way around it. Knowing that a solution is suboptimal and knowing what a better solution is are two very different things.

1 Like

Working vs not working is also a thing. Best way vs not best way is also subjective and circumstantial.

At any rate. Its definitely one legitimate method. For reference… I make a single call to compare that value in my uimanager. No where else. It really does come down to implementation in the end. GL

That’s exactly what I was trying to say. I have used that approach with lots of booleans in the past and it was horrible. I was just wondering if anyone was aware of a none-spaghetti solution :slight_smile:

Thanks @StarManta that will probably work for what I want :smile: Just one last thing. How would you handle cases where a layer only cares about some input so the layer below it can use the other inputs that weren’t handled in the upper layer?

You can have ProcessInput return a bool - “true” if the input was used, “false” if it wasn’t. If the input wasn’t used, the InputManager can send it down to the next one on the stack.