Movement Commands
Movement commands allow you to direct selected units to move to specific locations. The system handles pathfinding, formation preservation, and obstacle avoidance automatically.
Overview
When you issue a movement command:
- Selected units receive the command
- Pivot point is calculated from all selected units' positions
- Relative positioning maintains unit formation
- Pathfinding calculates routes for each unit
- Movement happens automatically with avoidance
The system is designed to feel natural and responsive while handling thousands of units efficiently.
Basic Usage
Selecting and Moving Units
The simplest way to move units:
- Select units - Left-click or drag-select units
- Right-click on the ground where you want them to move
- Units move - They automatically pathfind and avoid obstacles
Units maintain their relative formation when moving. If you select a group and right-click, they'll move to the new location while preserving their spacing.
How Formation Works
When you issue a move command to multiple units:
- The system calculates a pivot point (average position of all selected units)
- Each unit's target is calculated relative to this pivot
- This preserves the formation - units don't all converge to the same point
- Units pathfind individually but maintain their relative positions
Example:
- You select 10 units in a line formation
- Right-click 500 units away
- Units move to the new location, maintaining their line formation
Programmatic Usage
Using the Movement System Component
The easiest way to issue movement commands programmatically is through the Movement System component:
// Get the Movement System component from Player Controller
UAC_CPP_MovementSystem_Abstract* MovementSystem =
PlayerController->GetComponentByClass<UAC_CPP_MovementSystem_Abstract>();
// Issue move command to selected units
FVector TargetLocation = FVector(1000, 2000, 0);
MovementSystem->MoveUnits(TargetLocation);
Using the Spawner Subsystem Directly
You can also use the Spawner Subsystem directly:
// Get the Spawner Subsystem
USpawnerSubsystem* SpawnerSubsystem =
World->GetSubsystem<USpawnerSubsystem>();
// Issue move command
FVector TargetLocation = FVector(1000, 2000, 0);
SpawnerSubsystem->IssueMoveUnits(TargetLocation);
Movement commands only affect selected units. Make sure units are selected before issuing commands, or the command will have no effect.
How Movement Commands Work
Command Processing Flow
- Command Issued -
MoveUnits()orIssueMoveUnits()is called with target location - Selection Query - System finds all entities with
FUnitSelectedTag - Pivot Calculation - Average position of all selected units is computed
- Command Assignment - Each selected unit receives a
FMoveCommandFragmentwith:- Target location (relative to pivot)
- Distance from pivot
- Forward vector direction
- Command status
- Pathfinding - Each unit calculates its path to its target
- Movement - Units move along their paths with avoidance
Move Command Fragment
Each unit stores its movement command in a FMoveCommandFragment:
- Status -
Added(new command) orRunning(in progress) - Target Location - Final destination for the unit
- Mouse Position - Original click position (for reference)
- Distance - Distance from pivot point
- Forward Vector - Direction from pivot to target
- bHasActiveCommand - Whether command is active
The fragment is automatically managed by the system - you typically don't need to interact with it directly.
Customization
Movement Parameters
Movement behavior is controlled by the Movement Trait on your entity config:
- Max Speed - How fast units move
- Acceleration - How quickly units reach max speed
- Deceleration - How quickly units stop
- Turn Rate - How quickly units can rotate
Adjust these in your Entity Config Asset to change how units respond to movement commands.
Formation Behavior
The system automatically preserves formations, but you can influence this:
- Unit spacing - Controlled by avoidance radius in Avoidance Trait
- Formation shape - Determined by initial selection positions
- Relative positioning - Maintained automatically during movement
For tighter formations, reduce the avoidance radius. For looser formations, increase it.
Advanced Usage
Custom Movement Logic
If you need custom movement behavior, you can:
- Create custom processors - Process
FMoveCommandFragmentwith your own logic - Modify command data - Access and modify move command fragments directly
- Add custom tags - Use tags to mark units for special movement behavior
Movement Tasks
The system uses a task-based approach internally:
MoveTaskProcessor- Handles pathfinding and initial movement setupSteerToMoveCommandGoalProcessor- Handles steering toward the goal- Other processors handle avoidance, orientation, etc.
You can extend this system by creating custom processors that work with movement commands.
Best Practices
Issuing Commands
- Batch commands - Issue commands once rather than repeatedly
- Wait for completion - Don't issue new commands while units are still moving (unless intentional)
- Consider selection - Only selected units respond to commands
Performance
- Large groups - The system handles hundreds of units efficiently
- Formation preservation - Automatic, no performance cost
- Pathfinding - Cached and optimized per unit
User Experience
- Visual feedback - Consider showing move indicators where players click
- Command queuing - The system supports one active command per unit
- Cancellation - New commands automatically replace old ones
Common Issues
Units not moving
Possible causes:
- Units not selected - Verify units have
FUnitSelectedTag - No navigation mesh - Ensure navmesh exists and is built
- Invalid target location - Check that target is on navigable surface
- Missing Movement Trait - Ensure units have Movement Trait in their config
Solutions:
- Verify selection system is working
- Build navigation mesh in your level
- Check target location is valid
- Verify entity config has Movement Trait
Units moving to wrong location
Possible causes:
- Formation calculation issue
- Pivot point calculation error
- Pathfinding failure
Solutions:
- Check that multiple units are selected correctly
- Verify navigation mesh covers the target area
- Check unit positions are valid
Units not maintaining formation
Possible causes:
- Avoidance forcing units apart
- Pathfinding obstacles
- Units too close together
Solutions:
- Adjust avoidance parameters
- Ensure clear paths to destination
- Increase unit spacing if needed
Performance issues with many units
Possible causes:
- Too many pathfinding requests at once
- Complex navigation mesh
- Large number of selected units
Solutions:
- The system handles this automatically with time-slicing
- Optimize navigation mesh complexity
- Consider splitting large groups into smaller commands
Integration with Selection
Movement commands work seamlessly with the selection system:
- Selection - Units are marked with
FUnitSelectedTagwhen selected - Command - Movement command queries for selected units
- Execution - Only selected units receive and execute the command
- Deselection - Units can be deselected, but active commands continue
Deselecting units doesn't cancel their movement commands. They'll continue to their destination even if deselected.
Next Steps
Now that you understand movement commands:
- Learn about the Navigation System to understand pathfinding
- Explore Creating Units to configure movement parameters
- Review the Entity System to understand fragments and tags
Summary
Movement commands in Pioneer are simple to use but powerful:
- Select and right-click - Basic usage is straightforward
- Formation preservation - Automatic and efficient
- Pathfinding - Handled automatically
- Avoidance - Built-in collision avoidance
- Scalable - Works with thousands of units
The system abstracts away the complexity, letting you focus on your game's unique mechanics while providing reliable, performant unit movement.