Controllers

How to work with GS_Unit controllers — the possession model, player and AI controller setup, and switching control at runtime.

Controllers are the possession layer of GS_Unit. A controller is the intelligence — human input or AI logic — that owns and drives a unit at any given moment. Because both player and AI controllers share the same possession interface, your unit entities do not need to know what is controlling them, and swapping control at runtime requires no special-casing.

For architecture details, component properties, and extending the system in C++, see the Framework API reference.

Player Controller and Input Reader components in the O3DE Inspector

 

Contents


The Possession Model

Unit Possession Pattern Graph

Breakdown

Every unit has exactly one controller at a time, or no controller at all. Possession is established by calling Possess on the unit and released by calling DePossess. The unit fires UnitPossessed on UnitNotificationBus whenever ownership changes so other systems can react.

ConceptDescription
PossessionA controller attaches to a unit. The unit accepts input and movement commands from that controller only.
DePossessionThe controller releases the unit. The unit halts input processing and enters a neutral state.
UnitPossessed eventFires on UnitNotificationBus (addressed by entity ID) whenever a unit’s controller changes.
GetControllerReturns the entity ID of the current controller, or an invalid ID if none.
GetUniqueNameReturns the string name assigned by the Unit Manager when this unit was spawned.

Controller Types

GS_Unit ships three controller components that cover the full range of typical game use:

ComponentPurpose
GS_UnitControllerComponentBase class establishing the possession contract. Extend this for custom controllers.
GS_PlayerControllerComponentHuman-driven controller. Connects into the Input Data pipeline and routes player intent to the possessed unit.
GS_AIControllerComponentNPC controller. Provides the entry point for AI logic to issue movement commands through the same unit interface as player input.

Both GS_PlayerControllerComponent and GS_AIControllerComponent extend the base controller, meaning any code that works with the base controller interface works transparently with either type.


Player Controller

GS_PlayerControllerComponent registers itself with the Unit Manager on activation, making it visible to the game’s controller tracking system. It connects to the Input Data pipeline on the possessed unit so that raw input events are routed correctly as soon as possession is established.

Setup

  1. Add GS_PlayerControllerComponent to a controller entity (not the unit entity itself).
  2. Ensure GS_InputDataComponent and GS_PlayerControllerInputReaderComponent are on the unit entity.
  3. Call Possess to attach the controller to the target unit.

ScriptCanvas — Possessing a Unit


AI Controller

GS_AIControllerComponent gives AI logic the same possession interface as the player controller. An AI behavior system possesses a unit, then issues movement commands through UnitRequestBus or directly drives the unit’s Input Data component to simulate input. The unit processes those commands through the same mover stack it would use for player input.

ScriptCanvas — Handing a Unit to AI

// Called from your behavior tree or AI activation event when the NPC starts acting
[AI behavior activates]
    └─► [UnitRequestBus(unitEntityId) → Possess(aiControllerEntityId)]

[UnitNotificationBus(unitEntityId) → UnitPossessed(aiControllerEntityId)]
    └─► [AI logic begins issuing movement / action commands]

Switching Controllers at Runtime

Because possession is a simple attach/detach operation on the unit, switching from player to AI control (or back) is two calls:

[Trigger: cutscene starts, character incapacitated, etc.]
    └─► [UnitRequestBus(unitEntityId) → DePossess]
            └─► [UnitRequestBus(unitEntityId) → Possess(aiControllerEntityId)]

[Trigger: cutscene ends, character recovers, etc.]
    └─► [UnitRequestBus(unitEntityId) → DePossess]
            └─► [UnitRequestBus(unitEntityId) → Possess(playerControllerEntityId)]

The DePossess call ensures the previous controller’s input pipeline is disconnected before the new controller attaches, preventing stale input state from leaking between ownership changes.


Querying Controller State

ScriptCanvas NodeReturnsNotes
GetController (on unit)EntityIdCurrent controller entity. Invalid ID means no controller.
GetUniqueName (on unit)stringThe name assigned to this unit at spawn time.

ScriptCanvas


Standby and Controllers

When the Unit Manager broadcasts EnterStandby, both player and AI controllers should stop issuing commands. Player controllers automatically halt input reading. AI controllers must be suspended by whatever behavior system drives them. On ExitStandby, normal command flow resumes.

EventController Action
UnitEnteringStandbyHalt input reads, suspend AI commands.
UnitExitingStandbyResume input reads, restart AI commands.

Both events fire on UnitNotificationBus addressed by unit entity ID.


Quick Reference

NeedBusMethod / Event
Attach a controller to a unitUnitRequestBus (by ID)Possess(controllerEntityId)
Release a controller from a unitUnitRequestBus (by ID)DePossess
Know when possession changesUnitNotificationBus (by ID)UnitPossessed(controllerEntityId)
Get the current controllerUnitRequestBus (by ID)GetController
Get a unit’s nameUnitRequestBus (by ID)GetUniqueName
Know when unit enters standbyUnitNotificationBus (by ID)UnitEnteringStandby
Know when unit exits standbyUnitNotificationBus (by ID)UnitExitingStandby

Glossary

TermMeaning
PossessionThe act of a controller attaching to a unit and becoming its active intelligence
DePossessionReleasing a controller from a unit, halting its input processing
Player ControllerA human-driven controller that routes input from the Input Data pipeline to a unit
AI ControllerAn NPC controller that issues movement commands through the same unit interface as player input

For full definitions, see the Glossary.


See Also

For the full API, component properties, and C++ extension guide:

For related systems:


Get GS_Unit

GS_Unit — Explore this gem on the product page and add it to your project.