Possess / Un Possess / Get Controller¶
At a glance
Lives in: Blueprint API / Pawn - Main targets: Controller for
Possess and Un Possess, Pawn for Get Controller - Returns:
Possess / Un Possess return no success value; Get Controller returns
a Controller reference that can be None - Fails by: doing nothing
useful or returning None; no Blueprint failure pin - Official docs:
Possess,
Un Possess,
Get Controller,
and Controllers
The one-minute version¶
Possessmakes a Controller drive a Pawn. The controller is the brain; the pawn is the body.Un Possessmakes the controller let go of its current pawn. The pawn is now uncontrolled unless something else possesses it.Get Controllerasks a specific pawn, "who is driving you right now?" It can return aPlayerController, anAIController, another controller subclass, orNone.Possessis authority work. In multiplayer, the server normally decides possession; a client-side call does not make the server accept a new body.- Possession is not the same thing as camera view, attachment, actor Owner, or player-slot lookup. It changes the control link.
- The nodes do not spawn a pawn, choose a PlayerStart, create an AIController, fix input mappings, or return a success Boolean. You still need to verify the new control link.
What they actually do¶
The useful mental model is a two-way link:
flowchart LR
PC[PlayerController or AIController] -- possesses --> Pawn[Pawn or Character]
Pawn -- Get Controller --> PC
PC -- Get Controlled Pawn --> Pawn
Possess is called on the controller, not on the pawn:
Possess
Target = Controller
In Pawn = Pawn to control
The behavior is roughly:
pseudocode of the engine behavior - not engine source
function Controller.Possess(NewPawn):
if this machine is not authority for possession:
return
if NewPawn is None:
return
if Controller already has a pawn:
unpossess the old pawn
Controller.CurrentPawn = NewPawn
NewPawn.Controller = Controller
notify controller and pawn that possession changed
function Controller.UnPossess():
OldPawn = Controller.CurrentPawn
if OldPawn is None:
return
Controller.CurrentPawn = None
OldPawn.Controller = None
notify controller and pawn that possession ended
function Pawn.GetController():
return Pawn.Controller, or None
For a player, that link lets input and control rotation drive the pawn. For an AI pawn, it lets the AIController run behavior, path following, and movement requests.
The broader concept is covered in Possession.
When they fail (and what failure does)¶
Possess and Un Possess have no success or failed pin. Get Controller
returns None when the pawn is currently uncontrolled.
Common causes:
- The call ran on the wrong machine.
Possessis authority-only. A client can request a pawn switch through an owned server event, but the server performs the actual possession. - Target Controller is
None. There is no brain to drive the pawn. - In Pawn is
Noneor not valid. The controller cannot possess an empty or destroyed body. - The pawn was never auto-possessed. A placed player pawn may have the wrong Auto Possess Player setting. A placed AI pawn may have no AIController class or Auto Possess AI setting.
- The controller possessed something else. A controller normally drives one pawn at a time. Switching vehicles or respawning leaves the old pawn unpossessed.
- You checked too early or after destruction. During spawn, death, respawn,
or EndPlay,
Get Controllercan temporarily beNone. - Input or AI setup is the real problem. Possession can be correct while Enhanced Input mapping contexts, movement components, Behavior Trees, or NavMesh setup are still wrong.
Failure does not retry later, choose a fallback pawn, spawn a controller, or print a guaranteed warning for your project logic. Use prints and Is Valid checks to prove the controller, pawn, and machine before you blame input or AI.
The pattern everyone actually uses¶
For normal player start/respawn, let GameMode do the framework work:
GameMode Restart Player at Player Start
-> GameMode spawns/selects pawn
-> PlayerController possesses pawn
-> PlayerController/Pawn setup events rebind UI, input, and camera
Use explicit Possess when you intentionally own the swap:
Server-side PlayerController EnterVehicle
-> Is Valid VehiclePawn
-> Possess(VehiclePawn)
-> confirm Get Controlled Pawn == VehiclePawn
-> apply vehicle input mapping context on owning client
For AI debugging:
Enemy BeginPlay or debug key
-> Get Controller
-> Is Valid
-> Cast To BP_EnemyAIController
-> print controller name before debugging Move To / Behavior Tree
If the pawn has no controller, fix possession first. AI Move To cannot drive
a pawn that has no AIController.
The C++ twin, for the curious (our own example code):
void ATrainingPlayerController::PossessVehicle(APawn* VehiclePawn)
{
if (!HasAuthority() || !IsValid(VehiclePawn))
{
return;
}
Possess(VehiclePawn);
}
void ATrainingEnemy::BeginPlay()
{
Super::BeginPlay();
AController* CurrentController = GetController();
if (!IsValid(CurrentController))
{
return;
}
CachedAIController = Cast<ATrainingAIController>(CurrentController);
}
Possession is not view target¶
This is a common beginner trap:
- Possession decides which pawn receives control.
- View target decides which actor the PlayerController's camera manager uses for the camera.
You can view through a CameraActor without possessing it. You can possess a pawn and temporarily view through a death camera. Those are separate choices.
For camera cuts, use Set View Target with Blend. For body/control changes, use possession through the server/authority path.
Multiplayer rule¶
In a networked game, possession is server-owned state.
Beginner-safe shape:
Owning client presses "Enter Vehicle"
-> Run on Server event on owned PlayerController or pawn
-> server validates vehicle is usable
-> server calls Possess(VehiclePawn)
-> possessed pawn/controller state replicates
-> owning client updates local input/UI/camera presentation
Do not have the client call Possess locally and expect everyone else to agree.
It may change a local-looking reference briefly, but the server's state is the
one that matters.
Lookalikes - which one do I want?¶
| Node or setting | Returns / changes | Use when |
|---|---|---|
| Possess | Controller starts driving a pawn; no success return | Authority deliberately changes the controlled body. |
| Un Possess | Controller releases its current pawn; no success return | You need a spectator/uncontrolled state or a controlled swap. |
| Get Controller | Pawn's current controller, or None |
A pawn needs to know who is driving it. |
| Get Controlled Pawn / Get Pawn | Controller's current pawn, or None |
You already have the controller and need its body. |
| Get Player Controller | Player slot's controller, or None |
You need a local player/control/UI owner, not any pawn's driver. |
| Try Get Pawn Owner | AnimBP mesh owner if it is a pawn | You are inside an Animation Blueprint. |
| Spawn Default Controller | Creates default AI controller when configured | A pawn should get its AIController after spawn/setup. |
| Set View Target with Blend | Camera view changes | The player should look through another actor without changing control. |
| Set Owner | Actor network owner changes | You are fixing RPC/owner-only replication ownership, not control. |
Rule of thumb: Possession answers "who drives this pawn?" Actor Owner answers "which player connection owns this actor?" View target answers "what camera am I looking through?"
Going deeper¶
- Possession - the controller/pawn model and why AnimBP preview is different from runtime possession.
- Ownership and lifetime - actor Owner, component owner, possession, and Outer are different relationships.
- Player Start, Restart Player, and checkpoints
- normal framework respawn flow.
- Get Player Character / Pawn / Controller
- player-slot getters vs pawn/controller getters.
- AI Move To & the NavMesh - why AI movement needs an AIController and NavMesh.
- Set View Target with Blend - camera changes without possession changes.
- Official docs: Possess, Un Possess, Get Controller, Controllers, and AController.
- Engine source (requires engine access - we do not reproduce it here):
AController::Possess,AController::UnPossess,AController::SetPawn, andAController::OnRep_PawninEngine/Source/Runtime/Engine/Private/Controller.cpp;APawn::PossessedBy,APawn::UnPossessed, andAPawn::GetControllerinEngine/Source/Runtime/Engine/Private/Pawn.cpp.