C++ - Architecture: How to design a local coop game where characters have different input schemes ?

Hey unreal folks,

this is my first post and I really did a lot of research on the topic before posting here. But now I found several possible solutions and I’m just not sure what is the proper way.

Problem

We are currently developing a local coop game that is a mix of an action game for one player and a puzzle game for the second one. Our actual problem is the input that is currently handled by a player controller that casts on every action mapping delegate received to determine if the possessed Pawn is from type PlayerA or PlayerB to then call the right function.

Let me give you a specific example:

  • We have two action bindings for
    the Button B (XBox Controller)
    currently called “B”
  • When the delegate is called we cast the possessedPlayer to check whether it shall call PlayerA->Jump or PlayerB->Blink
  • I’m totally unhappy with the situation that I have to cast everytime we receive an Input just to check wether I have possessed action/puzzle char

Solutions

1) Create 2 PlayerControllers and swap them by using GameMode::SwapPlayerController(Old, New)

I found this function during research but I’m not happy with creating a Player with PlayerControllerA to immediately switch it to use PlayerControllerB,

2) Shift responsibility to the Charatcer class

Another thought would be to delegate the decision making to the Character class by passing down an enum value like **E_BUTTON_B **from the PlayerController to the Character. We could write a macro that creates this enum based on our input mappings and then delegate the decision to a generic Character->ProcessInput(EnumValue) function. I’m also not quite happy because then the PC does not make so much sense to me.

3) Cache the possessed Pawn to avoid the cast

Another idea would have been to cache the type of the possessed Character whenever the PC possesses a Pawn. This would get rid of the cast per input delegate call.

I would be very glad for advide and any hint how you folks solve such issues in your games. Our main goals are separation of concern, good maintainability and input rebinding.

Cheers and have a nice day,

Parzival

Typically you will want to define the input that is Pawn agnostic / global inside the PlayerController and then define Pawn specific input inside each Pawn.

So one way, if you are ok with inheritance, is to make a base Character class that has all the functionality that all characters share and then make a child for each input scheme. Then you would inherit from each of those characters depending on your final character desired input scheme.

If you want a cleaner implementation you could try making a custom component to handle your imput schemes

As @Sveitar said, your character related input should be setup on the character class. For that you would want to override APawn::SetupPlayerInputComponent(UInputComponent * MyInputComponent). On the APlayerController::SetupInputComponent() you would usually only want to setup bindings to open the menu for example.