when to script in the character blueprint and when in player controller?

I’v been learning ue4 blueprints by reading the templates’ blueprints, however one thing I learned on the forums is that the templates are terrible with good scripting practices, for my luck. for example, I’ve never seen a template using a dedicated game mode or a player controller blueprint, so until recently I had no idea what those were for. well turns out I’m still not sure about some things, so what do you put into your character and what into the player controller?

here’s an example of a character I’m making:

all of it is in my character blueprint. I’d still have to cross check crouching and walking so I’m not able to exploit crouching movement speed by toggling walk mode while crouching, and I also want to add a sprint mode with stamina, so this can get complex. and I’m not sure what should go in there and what I should move to the player controller

I personally try to keep the Character BP itself limited to functionality related to the “physical” aspects of the in-game pawn and put everything else in components or the controller. E.g., InputAction and InputAxis events are only in my controller class and nowhere else.

I’m doing this because A) my Character pawn might change during gameplay (I want the player to be able to switch between the default humanoid character and a “free camera” pawn in some situations), and B) the Character isn’t the only object that will ever respond to input (for example, the same InputAction will do different things depending on if the game is in default mode, dialogue mode, or menu mode) and I’ve found that things can behave in weird ways if more than one BP attempts to process the same InputActions.

But the “best” method will probably vary depending on your requirements…

hey, thanks.

can you give an example of a physical aspect of the pawn that you script inside it’s blueprint? so in your case you would put all the code in the image I linked into the player controller instead?

By “physical” I guess I mean functionality related to how the pawn appears in the world, like movement, animation, anything directly affecting the pawn’s skeletal mesh, etc. So Add Movement Input, rotations, jumping/crouching, etc. go in my pawn/character classes. My reasoning is that I want to encapsulate these functions in separate classes if I’m expecting them to vary among pawns. E.g., my default biped has a walking animation BP, can move, rotate, etc. but can’t fly. My “free camera” can fly and isn’t affected by gravity but doesn’t need an animation BP. If I had something like a stationary turret, it would have its own anim BP and could rotate but wouldn’t fly or even move (so it wouldn’t need any Add Movement Input nodes). In Menu mode, movement of all pawns is disabled and “MoveForward” changes the focus to the next button instead.

All of these classes react differently to the same input, so I want the input to be handled in a separate class in order to decouple it from “responses” to input. In my case, I have generic “InputPressed” and “InputReleased” event dispatchers on my PlayerController class (with an enum parameter specifying which particular InputAction was received), and I bind Character/Pawn/UI events to it at runtime, but there are probably other ways to get the necessary classes to “listen” to the PlayerController. I could also put variables like the player name and XP or money on the PlayerController and have that persist between pawn changes, although those might be better to put on something like a custom PlayerState (in multiplayer) or GameInstance (if they need to persist between level changes).

Of course, a lot of this would be unnecessary if I only had a single Character for the player to possess, so your needs might be different.

Agree, best practice docs / examples in BP are lacking. So many templates hardcode to PC0 too. So if your game adds local multiplayer (PC0-8 etc), then there will be be a lot of rework. There are some general past posts about this, if I can find them I’ll link below later. Basically to add to what DysD said… PC is better for generic input (re-mapping keys / gamepad inputs), camera switching, sending inputs to multiple actors / objects (such as BP interactable objects dragged into the level), and multiplayer of course.

But if you’re still in the prototyping phase, the benefits may not be obvious or worth it yet, especially with all the built-in global helpers for accessing Player-Controller from everywhere. Plus sometimes you can find yourself calling back into PC to set something (a state, an actor reference or a variable etc) that later needs to be accessed directly in the Character or Pawn Blueprint etc. When that happens, you may find yourself jumping through artificial hoops just to keep the communication alive, which doesn’t make sense…

I think I get it now. so according to this logic, none of the script I linked would go into player controller, right?

I once scripted a way to do an action only once when pushing a gamepad thumbstick up/down, and do another action when releasing the thumbstick, no matter if you had rotated it to the sides. I couldn’t have used pre existing action mappings for press and releasing the axis because I needed to retain the rotation information on the moment of releasing the stick, so I had to program a deadzone where the action would start and end, before the axis information zeroes. so I made this:

in this case, still following your logic, would you put this script into the player controller blueprint, and then instead of printing a string (or let’s say it’s any other action like jump) in the end nodes, make custom events, and then in the character blueprint on those events assign them to do the jump action?

this makes sense, also kinda explains why most templates don’t deal with player controller.

I don’t plan to make multiplayer games in the forseeable future, so I suppose it’s not of much use to me, it’s just that a lot of times while trying to learn something and searching online I face mentions to all those things that I don’t quite understand what they are used for, and it’s not very obvious at first sight

for example, the term player controller, I had no idea what the hell that was all about. when they say “player” as in posses player 0, I wouldn’t know if they are talking about the person who is playing the game or the character being played, or where does that player 0 thing comes from, same thing to controller, is about the game controller I’m holding in my hand? or is it me since I’m the one controlling the game? is it an interface that controls the game?

I kinda understand what this stuff is about based on the context, but it gets really confusing really fast. there’s just a lot of things that are hidden, underlying mechanisms that you never realise they exist until you find them, and begginner tutorials not ever deal with them, and more advanced ones are way too specific and require you to have previous understanding of those things. there’s some sort of gap there I’m trying to fill.

In your above example, you’d still have Add Movement Input, Jump, Crouch etc. scripted in your Character, since those are pawn-specific and a different pawn might react differently to those inputs (e.g., with different acceleration rates or max speeds) or might just ignore them (e.g., a car probably shouldn’t jump or crouch). The main difference in my example is that you don’t access the InputAction nodes directly in the Character BP, you have BP-specific events that are bound to the PlayerController’s event dispatchers. This way 1) the PlayerController doesn’t need to know anything about the pawns it controls, so you’re free to add/modify/delete controlled pawn classes without “breaking” the PlayerController, and 2) the controlled pawns don’t need to know the exact InputActions/InputAxes that you’ve defined, so you’re free to add/modify/delete them without “breaking” any of the pawns.

Re: InputAxes, I had something similar with MoveForward/MoveRight when I wanted them to change the UI focus. I just processed the InputAxis events directly (in my PlayerController), since they’re apparently fired OnTick anyway. I don’t have it in front of me, but basically the first was a Branch checking if ABS(axis value) > 0.1, False means do nothing, True means fire an event dispatcher (“Up” if axis value is positive, “Down” if negative). I think I had a DoOnce node before the event that reset after a delay, to prevent the Up/Down event from firing too quickly when the input was held down.

Also as ClavosTech said, this may not be worth the trouble if your game is simple enough. You’d also lose the benefits of decoupling if you for some reason need your pawns to change the state of the PlayerController. (You could potentially mitigate that problem using interfaces or components - but that’s an example of additional “hoops” to jump through)

In Epic tech, there’s a long history of Player-Controller vs Pawn or (AI-Controller vs AI-Pawn). So that’s why people are used to it… At the simplest level consider this… In a game you can have multiple Characters and multiple Vehicles interacting all the time. Some of those are real-world human Players, some are Bots (npc’s). So you need a structure on top of this, that allows you to control or supervise these actors and their interaction, movement or weapon fire etc.

When a human controls a Character (Pawn), you’re not concerned with the minor details of how they’re choosing to move around the map or when they decide to shoot or not etc. But you still have to capture keyboard / gamepad input (which is always done in Player-Controller), and route that information to the Character (Pawn) to do the actual movement / shooting. When the on-screen character is a Bot, you’re not concerned with keyboard / gamepad input. but you still need logic to control how that Character gets around the map (obstacle avoidance etc), and how it detects enemies and knows when and where to shoot etc.

In that sense devs often talk about Player-Controller (PC) as the mind or will of the Character, and the Pawn as just a zombie body waiting to be told where to go. In a typical game, each human player (PC) gets to have multiple lives (Pawns). That’s why they’re separate ;)… But honestly it doesn’t matter that much in single-player. You can stick to just keeping the code simple and readable and be a purist later. Also, in single-player the hero Character (Pawn) often drives the gameplay forward. So for example entering or exiting vehicles can be done in Character (Pawn) or PC, including changing skin (skelmesh). Essentially, using the additional gameplay framework classes just adds more structure. But its up to you to choose if you want to leverage that, so long as your code is simple, readable and easy to follow / maintain…

thanks guys, that was very enlightening. let me know if I get this right this time

so putting it the simplest way, if I wanted to decouple my code for any reason, the simples jump action would go like this:

-in the input section of project settings, I’d add a jump input action and assign all the buttons from the controllers that I want the player to use for jumping, such as spacebar, gamepad face button down, etc;
-in the player controller blueprint I’d add a jump input action event that just triggers a custom jump event;
-in the pawn blueprint, I’d add the custom event for jumping rather than the input action event directly, so it could be triggered from a different code than human input;
-if that pawn could also be an NPC, I’d have an AI blueprint that would say something like “if someone tries to kick the npc in the balls, trigger custom jump event”;
-also if my game was sort like assassin’s creed or something, holding sprint and moving close to a ledge could trigger the custom jump event.

does this sound right? it’s making sense to me.