When we start creating games in Unreal Engine, it is common to focus first on what appears on screen: a character walking, the camera following the player, enemies attacking, a health bar going down, and items being collected.
But behind these actions, there is a structure that organizes who controls what, where the game rules live, and how data is shared.
That structure is the Gameplay Framework.
In this article, we will look at the main classes in this framework, how they connect, and how elements such as GameInstance, GameMode, GameState, PlayerController, PlayerState, and Character are initialized.
1. What is a Gameplay Framework?
A framework is, basically, a set of classes, systems, and tools created to provide a structural foundation for developing a project. Ideally, this foundation should be modular enough to adapt to different needs.
In Unreal Engine, the Gameplay Framework helps organize gameplay logic and manage elements such as PlayerController, AIController, Character, Pawn, GameMode, GameState, PlayerState, and others.
This allows the developer to use an architecture already prepared by the engine instead of building the entire structure of the game from scratch.
When we start studying Unreal, it is common to focus first on what we want to see working: the hero walking, the camera following the character, an enemy attacking, a health bar decreasing, a door opening, or an item being collected.
All of that is exciting, but behind these actions there is a very important structure worth understanding. That structure is the Gameplay Framework.
Understanding this foundation helps avoid many common problems, especially when the project starts to grow.
2. Why does the Gameplay Framework matter?
In a small prototype, it is tempting to put everything inside the most direct class we are already working with. In my case, that class was often the PlayerCharacter.
At first, this seems to work well. We place input, movement, health, attack, inventory, victory conditions, UI, and any other logic directly in the character. It is fast, visual, and gives a feeling of progress.
The problem appears over time.
The character class starts growing too much. It begins to control things that should not be its responsibility. What was once simple to change becomes difficult to maintain, debug, and reuse.
From that point on, any change can break another part of the project. Development, which once felt fluid, becomes a sequence of delicate adjustments to avoid destroying something that was already working.
To avoid that problem, we need to distribute responsibilities better.
Unreal already offers a natural separation for this. The Gameplay Framework exists precisely to help divide the weight across several classes designed for different roles. But it is important to remember: it does not remove the need to think about architecture. What it offers is a foundation so that architecture does not need to start from zero.
Next, we will look at the main classes in this framework. You do not need to memorize all of them at once. The most important part is understanding the role of each one and starting to apply that logic to your own projects.
At the end, I included a small challenge to help make these ideas more practical.
3. What are the main classes in this framework?
To avoid confusion and avoid simply listing many names, I find it useful to separate these classes into three large groups: structure and rules, control and possession, and world and presentation.
This split is not an official Unreal rule. It is just a didactic way to understand the role of each class within the game’s architecture.
Structure and rules classes
These are responsible for keeping the game organized at a high level.
In this group we have:
GameInstanceGameModeGameStatePlayerState
Control and possession classes
These are responsible for connecting decisions and commands to controllable entities.
In this group we have:
ControllerPlayerControllerAIControllerPawnCharacter
World and presentation classes
These are responsible for representing objects, components, and the way the player perceives the game.
In this group we have:
ActorActorComponentCameraHUDUI
In other words:
Some classes organize rules, others connect the player or AI to controllable entities, and others give shape to the world the player sees.
When we analyze Unreal’s hierarchy, we can see that many important Gameplay Framework classes derive from Actor, such as Pawn, Character, Controller, GameMode, GameState, PlayerState, HUD, and CameraActor.
That does not mean they all have the same role in the game world. Some represent physical entities, such as characters and objects. Others represent rules, state, control, or presentation.
That is why understanding each class’s responsibility is more important than memorizing the inheritance tree.
From here, let us look at each of them more calmly.
4. Actor: the base of almost everything
Actor is the base class for any object that can exist in a Level.
An enemy, a door, a weapon on the ground, a projectile, a moving platform, a collectible item, or a damage volume can all be Actors.
In simple terms:
If something needs to exist in the game world, it will probably be an
Actoror inherit fromActor.
Actors can have components, their own logic, a position in the world, events, and behavior. But an Actor by itself does not necessarily mean it is controllable by the player.
For that, we enter the concept of Pawn.
5. Pawn: something that can be possessed
Pawn represents an entity that can be controlled.
It can be a humanoid character, a car, a spaceship, a free camera, or any other entity that receives control from a player or AI.
The important word here is: possessed.
In Unreal, a Pawn can be possessed by a Controller. This means the decision logic can be separated from the physical entity that exists in the world.
A simple way to think about it is:
- The
Pawnis the body. - The
Controlleris the one giving orders.
This separation is very powerful because it allows the same Pawn to be controlled by different sources. A character can be controlled by the player at one moment and by AI at another, depending on the game’s logic.
6. Character: a specialized Pawn
Character is a specialized version of Pawn, commonly used for characters that move by walking, jumping, falling, or navigating through the world.
It already includes useful structures such as:
Capsule ComponentSkeletal MeshCharacter Movement Component- support for common character movement
- integration with collision and movement physics
In practice, if you are creating a playable humanoid character, an enemy that walks around the map, or an NPC with traditional locomotion, you will probably start with Character.
But that does not mean everything needs to be a Character.
A car, for example, may make more sense as a Pawn. A strategy camera as well. A spaceship may require its own implementation.
The question should not only be:
Can I make this with
Character?
The more important question is:
Does this entity really need Unreal’s default character behavior?
If the answer is yes, Character is probably a good choice. If not, maybe a Pawn or even an Actor is enough.
7. PlayerController: the bridge between the player and the game
PlayerController represents the player inside Unreal’s logic.
It receives input, interprets intentions, and controls a Pawn.
This is important because PlayerController is not the character. It is the player’s control layer. The character can die, change, respawn, or be replaced, but the PlayerController continues to represent that player.
A common example:
- The player presses the attack button.
- The
PlayerController, or the input system connected to it, interprets that command. - The
PawnorCharacterexecutes the corresponding action.
In small projects, a lot of logic often goes directly into the Character. But in more structured games, it is worth thinking more carefully about what belongs to the PlayerController and what belongs to the Character.
Practical rule:
- Player input and intention tend to live in the
PlayerControlleror systems connected to it.- Physical execution of the action tends to live in the
PawnorCharacter.- General match rules should not live in either one.
8. AIController: control for non-playable characters
Just as PlayerController controls a Pawn based on a human player’s actions, AIController controls a Pawn based on artificial logic.
It can use Behavior Trees, Blackboards, perception, navigation, and other systems to decide what an enemy or NPC should do.
This separation keeps the architecture cleaner.
The enemy does not need to be “the entire AI.” It can be only the body that executes actions, while the AIController decides when to attack, chase, patrol, or flee.
9. GameMode: the rules of the game
GameMode defines the main rules of the match or game mode.
It exists only on the server in multiplayer games, but even in single-player it remains an important class for organizing global rules.
Examples of GameMode responsibilities:
- define which
Pawnwill be used by the player; - control match start and end rules;
- decide victory or defeat conditions;
- choose
PlayerController,GameState,HUD, and default classes; - manage rules specific to a game mode.
A common mistake is putting match rules inside the character.
For example:
When all enemies die, the level ends.
This logic does not belong to the player’s Character. It probably belongs to GameMode, GameState, or a specific system responsible for managing the level.
Unreal’s documentation also separates GameMode and GameState well: GameMode concentrates match rules, while GameState stores information about the current state of the game.
10. GameState: the shared state of the match
GameState stores information about the current state of the game.
If GameMode defines the rules, GameState represents the data that describes how the match is right now.
Examples:
- remaining match time;
- team score;
- current level state;
- number of connected players;
- information that needs to be known by all players.
In multiplayer, GameState is especially important because it can replicate information to clients.
A simple way to think about it:
GameMode: decides the rules.GameState: reports the current state of those rules.
11. PlayerState: information about each player
PlayerState stores data related to a specific player.
It is useful for information that belongs to the player, but not necessarily to the current Pawn.
Examples:
- player name;
- score;
- team;
- death count;
- match statistics;
- data that continues to exist even if the character dies and respawns.
This is different from storing current health, stamina, or ammunition. Those values usually belong to the Pawn, the Character, or one of its components.
But the player’s score, for example, makes more sense in PlayerState.
12. HUD and UI: presentation is not game rules
Unreal also has interface-related classes, such as HUD and Widgets.
One important point is not to mix UI with game rules.
The health bar shows health, but it should not own the health. The widget can observe or receive data from the character, a component, or another system, but the real logic needs to live somewhere else.
A good separation would be:
- The
Characteror an attribute component stores health. - An event reports that health changed.
- The Widget updates the visual bar.
This way, the interface only presents the state of the game without directly controlling the main rule.
13. How do these classes connect?
A common structure would look like this:
GameMode
|-- Defines match rules
|-- Chooses default classes
`-- Controls game start/end
GameState
`-- Stores general match state
PlayerController
`-- Receives input and controls a Pawn
PlayerState
`-- Stores persistent player data
Pawn / Character
`-- Represents the controlled entity in the world
AIController
`-- Controls enemy or NPC Pawns
HUD / Widgets
`-- Show information to the player
The central point is that each class has a responsibility.
When these responsibilities are clear, the project grows in a healthier way.
14. In what order do these classes appear in the game?
Besides understanding the responsibility of each class, it is also important to understand when they come into existence.
A very common question when studying Unreal is:
Where should I put my initialization logic?
The answer depends a lot on which class you are using and when that class exists during gameplay.
In a simplified way, we can think of a sequence like this:
Game starts
`-- GameInstance is created
A map/level is loaded
|-- GameMode is created
|-- GameState is created
`-- World Actors begin initialization
A player joins the match
|-- PlayerController is created
|-- PlayerState is created
|-- Pawn/Character is spawned
`-- PlayerController possesses the Pawn/Character
Gameplay begins
|-- BeginPlay for Actors
|-- input logic
|-- UI
`-- gameplay systems running
This sequence is a didactic simplification. The exact order can vary depending on context, especially in multiplayer, seamless travel, level streaming, respawn, map transitions, and specific project settings.
Even so, it helps explain an important idea: some classes belong to the entire game execution, others belong to the map or game mode, others to the player, and others to the body that exists in the world.
GameInstance: created with the game and survives between maps
GameInstance is one of the first important classes to exist.
It is created when the game starts and remains alive while the game is running. Unlike classes such as GameMode and GameState, it is not recreated every time you change maps.
Because of that, it is useful for data and systems that need to survive between levels.
Examples of use:
- session data;
- global settings;
- references to persistent systems;
- temporary data between maps;
- general game state outside a specific level.
But it is important to be careful: GameInstance should not become a global storage place for everything.
It is not the best place for combat-specific logic, character health, level rules, or enemy behavior.
A good question to decide whether something belongs in GameInstance is:
Does this information need to keep existing even when I change maps?
If the answer is yes, it may make sense for it to be in GameInstance.
GameMode: created with the map and defines match rules
GameMode is created when a map is loaded and defines the main rules of that game mode.
It decides, for example, which PlayerController, Pawn, HUD, GameState, and other default classes will be used in that map or mode.
This is where rules such as these belong:
- how the match starts;
- how the match ends;
- which character the player will use;
- what happens when the player dies;
- how a new player joins the game;
- what the victory or defeat conditions are.
In multiplayer, GameMode exists only on the server. This is very important. If you put information in GameMode expecting all clients to access it directly, you may run into problems.
Practical rule:
The
GameModedecides the rules, but it is not the best place to store information that all players need to see directly.
For that, we use GameState.
GameState: created with the match and stores shared state
GameState also exists during the match, but it has a different function from GameMode.
While GameMode defines and executes rules, GameState stores information about the current state of the game.
Examples:
- remaining time;
- general score;
- current level state;
- number of alive enemies;
- match phase;
- current objective;
- data that needs to be known by all players.
A simple way to separate them is:
GameMode -> decides what should happen
GameState -> shows the current state of the game
For example, if all enemies die, GameMode can decide that the level is over. But the number of remaining enemies can be stored in GameState, especially if that information needs to appear for other players or in the UI.
PlayerController: created when the player joins
PlayerController represents the player inside the match.
It is usually created when the player joins the game. After that, it can possess a Pawn or Character.
An important point is that PlayerController can continue to exist even if the character dies, is destroyed, or is replaced.
This makes it a good place for logic related to player intention, such as:
- input;
- camera commands;
- opening menus;
- target selection;
- UI interaction;
- control logic that should not die with the character.
But it should not be used as a storage place for everything.
The character’s health, for example, normally should not be in PlayerController, because health belongs to the controlled body, not to the abstract player.
PlayerState: created to store player data
PlayerState stores information about a specific player inside the match.
It is very useful for data that belongs to the player but should not be lost when the character dies.
Examples:
- player name;
- score;
- team;
- number of deaths;
- match statistics;
- progress inside that match.
The difference between PlayerController, PlayerState, and Character can feel confusing at first, but a simple way to think about it is:
PlayerController -> the player giving commands
PlayerState -> the player's data in the match
Character -> the player's body in the world
If the character dies and respawns, the PlayerState can continue storing the score. The previous Character, however, may have been destroyed.
Pawn or Character: created when a controllable entity appears in the world
Pawn or Character is usually created when the game needs to place a controllable entity in the world.
For the player, GameMode can define which DefaultPawn class will be used. After that, the PlayerController possesses that Pawn.
For enemies, they can be placed directly in the map or spawned during gameplay. Then, they can be controlled by an AIController.
The Character should store information and behaviors connected to the physical body in the world, such as:
- movement;
- collision;
- current health;
- current stamina;
- animations;
- attack;
- received damage;
- physical interaction with the environment.
Practical rule:
If the logic depends on the body that exists in the world, it probably belongs to the Pawn, the Character, or a component connected to it.
HUD and UI: usually created after there is game context
The interface usually depends on data that comes from other classes.
For example, a health bar needs to know which character it is observing. An enemy counter needs to know the state of the level. A victory screen needs to know that the match has ended.
Because of that, it is common for UI to be created or updated after references to PlayerController, PlayerState, Character, or GameState already exist.
But UI should only present information or send player intentions. It should not own the main rules.
For example:
Wrong:
Widget decides whether the player died.
Better:
Character or attribute system detects death.
GameMode or another system decides what happens next.
Widget only shows the defeat screen.
15. Where should initialization logic go?
A practical way to think about initialization is to separate it by scope:
| Scope | Likely class | Examples |
|---|---|---|
| Whole game | GameInstance | global settings, data between maps, persistent systems |
| Level or game mode | GameMode / GameState | start round, control victory condition, store match state |
| Player | PlayerController / PlayerState | input, player HUD, individual score, team |
| Body in the world | Pawn / Character / components | health, stamina, movement, attacks, collision |
| Visual | HUD / Widgets | health bar, current objective, messages, victory/defeat screens |
16. Practical example: a simple action game
Imagine a third-person action game.
The player controls a character who can walk, attack, dodge, and defeat enemies. The level ends when all enemies are eliminated.
One possible division would be:
GameInstance
Responsible for:
- keeping global settings;
- storing temporary data between maps;
- storing references to persistent systems, if needed.
GameMode
Responsible for:
- starting the level;
- checking victory conditions;
- defining what happens when the player dies;
- deciding when the match ends.
GameState
Responsible for:
- number of remaining enemies;
- current level state;
- match time, if it exists.
PlayerState
Responsible for:
- player score;
- number of deaths;
- team, if it exists;
- player data that continues after respawn.
PlayerCharacter
Responsible for:
- movement;
- attack;
- dodge;
- animations;
- collision;
- attributes such as health and stamina, possibly through components.
PlayerController
Responsible for:
- player input;
- target switching;
- camera commands;
- opening menus;
- interpreting player intention.
AIController
Responsible for:
- chase logic;
- attack decision;
- patrol;
- reaction to the player.
UI
Responsible for:
- showing health;
- showing stamina;
- showing the current objective;
- displaying victory or defeat screens.
This organization prevents the Character from becoming the god class of the project.
17. The most common mistake: putting everything in Character
At the beginning, it feels natural to put everything in the character, because it is at the center of the experience.
But this creates several problems:
- the
Characterbecomes difficult to understand; - any change can break several parts of the game;
- the logic cannot be reused easily;
- multiplayer becomes more complicated;
- systems such as AI, UI, and level rules become too coupled.
Good architecture does not mean creating dozens of classes without need. It means placing each responsibility in the right place.
The goal is not to complicate the project. It is to avoid making everything depend on a single class.
18. Blueprint or C++?
The classes we saw here can be used both in Blueprint and in C++.
Blueprint is excellent for prototyping, fast iteration, and visual logic. C++ is powerful for more robust systems, performance, large-scale organization, and reusable foundations.
A common approach is:
- create the base in C++;
- expose variables and events to Blueprint;
- adjust behavior and balancing in the editor.
But to learn the Gameplay Framework, Blueprint can be a great entry point. The most important thing is understanding the architecture before worrying too much about the language.
Before asking “Should this be Blueprint or C++?”, it is worth asking:
Where should this responsibility exist inside the structure of the game?
Once that answer is clear, choosing between Blueprint and C++ becomes much simpler.
Conclusion
The Gameplay Framework is one of the most important foundations for anyone who wants to go deeper into Unreal Engine.
It is not just a list of classes to memorize. It is a way to think about the structure of a game.
When you understand the difference between Actor, Pawn, Character, PlayerController, GameMode, GameState, PlayerState, and GameInstance, you start making better decisions about where to place each part of the logic.
But there is another point just as important as knowing the role of each class: understanding when each one exists.
GameInstance follows the whole game execution. GameMode and GameState organize the match. PlayerController represents the player. PlayerState stores that player’s data. Character represents the body in the world. UI presents information to the person playing.
When this separation becomes clear, the project grows in a healthier way.
Especially in larger games, separating responsibilities well is what allows the project to keep evolving without becoming a mess that is difficult to maintain.
Challenge
Think about a simple game you would like to create, such as an action, platformer, horror, or adventure game.
Now try to answer:
- What needs to exist from the start of the game and survive between maps?
- What should be configured when the level starts?
- What would stay in the
Character? - What would stay in the
PlayerController? - Which rules would belong to
GameMode? - Which information should go to
GameState? - What data would make sense in
PlayerState? - Is the UI only showing information, or is it also controlling game rules?
This exercise helps turn the Gameplay Framework into something practical, not just a list of Unreal classes.
Reference
This article was based on Epic Games’ official Unreal Engine documentation about Unreal Engine’s Gameplay Framework.
