Platformer Template

Update June 2022

June 2022 Update
  • Refactored movement component with numerous bug fixes, now has its own gravity function (this will absolutely break everything done with previous version. Painful but necessary)
  • Turned surfaces into volumes (now they will keep friction settings as long as pawn is inside the volume)
  • New volumes: Continuous Damage (will damage pawn every x time); No Input (prevents actions and movement)
  • New Moving Platforms with continuous movement or pressure activated option
  • New higher poly loop mesh (smoother ride)
  • New Fan actor will propel pawns and mines to x height
  • New Interactable Button will interact with a specified actor that implements the interaction interface. I added a Door as example (move camera towards button and press E)
  • Jumpers no longer reset velocity before jumping so actors will keep their previous movement direction
  • Many tweaks to settings in movement component and in enemies
  • Unreal Engine 5 support

NOTES: I locked the project to 60 fps and tried as much as possible to make everything frame rate independent, but it’s likely that some forces will move differently at very low framerates


3D Platformer Template is a group of Blueprints made for classic platformer mechanics in a 3D environment. The custom movement Actor Component can be added to any Pawn. In addition to the movement Actor Component, there are blueprints for basic pickups, mines, mine spawner, jumpers, damaging spikes, moving platforms, fans, interaction buttons, doors and three types of enemies.These enemies are examples of pawns that use the Platformer Actor Component to move around.

The movement component uses the default physics collisions but will set velocities and rotations of the pawn manually which should give certain non-physical movement aesthetics very characteristic of classic platformers.

[Unreal Engine Marketplace Link]


AC_PlatformerMovement assumes three important things: that the actor that you’re adding it to is a Pawn and that the component doing the physics and movement is RootComponent, and that it’s a Sphere or Box Primitive Components

This component uses the default physics collisions but will set velocities and rotations of the pawn manually so the Physical Material should always be frictionless as specified in PhysicsSetup

Another important consideration to have is that this Actor Component is not extended from PawnMovementComponent as that class is not accessible to Blueprints, so using this component in a large project with hundreds of ticking pawns will have to be refactored in C++ for better performance. A workaround to this is to have some system that handles this, example: turn off and on ticking as the player moves into their area


There are two important Pawns in this template (BP_PlayerPawn and BP_Enemy) that implement AC_PlatformerMovement, both are ready to use, but in case you want to use your own class, this setup should be done before the component works as intended:

  • Add a Sphere or Box Primitive Component as Root Components to your Pawn. Their collision type should be set as Pawn or Enemy if not a player.
  • Add a AC_PlatformerMovement component. In case you need to do the Physics setup manually elsewhere, copy the contents of the function PhysicsSetup in this component.
  • Call SetTraceVector on AC_PlatformerMovement, this will set a line trace that will look for the ground. Extend it slightly beyond the collision component so the pawn doesn’t lose traction too fast in odd geometry, like loops.
  • In the component’s details, set your WalkableObjects types if necessary (default is WorldStatic, WorldDynamic and PhysicsBody)
  • Feed your Forward and Right inputs to the SetInput function

AC_PlatformerMovement Public Variables

WalkableObjects: Walkable Object types. Even invisible objects will be walked on if they respond to line traces

Debug: this will show ForwardForce and Friction lines, the line trace that detects the ground and various strings about the state of the pawn

UsesGravity: do not change during play

DriftMultiplier: 0 is when velocity is always turned to the Pawn’s ForwardVector. 1 is when velocity only updates when any force is made. Used when walking on surfaces like Ice

StaticFriction: Friction coeficient when stopped. Make sure ForwardForce can win against this to start moving. These are not physically accurate

KineticFriction: Friction coeficient when moving

AirKineticFriction: KineticFriction in air

AirStaticFriction: Static friction in air

StaticFrictionSpeed: Below this speed it’s applied the Static coefficient, else applied the Kinetic. Setting a high value to this prevents the pawn from sliding down in slopes although ForwardForce will have to be tweaked accordingly.

MaxSpeed: the maximum speed. default is 6000 cm/s (216 Km/h)

ForwardForce: force made forward and backward

YawForce: not a physical force but it’s the rate at which the Pawn turns

FastRotInterp: this is an interpolation rate for pawn rotations done when on ground (if too low, the pawn won’t rotate fast enough to do loops)

SlowRotInterp: this is an interpolation rate for pawn rotations done when in air

BrakingMultiplier: fraction of ForwardForce that will be used for Braking. Higher will brake faster

JumpForce: force for jumps

AirControl: coeficient for player control when on air. Usually below 1.0

MinAttackTime: the shortest duration of any jump attack (in general you want this lower or same as other attack types)

HomingAttackForce and DashAttackForce: how fast to home in on enemy during this attack type

HomingAttackDuration and DashAttackDuration: the shortest duration of this attack type

ForwardInput and RightInput: usually you will want to use SetInput function and feed your inputs, but I kept them exposed in case you want to set them separately for AI pawns

RightInputInterpSpeed: an interpolator float to help with hard camera rotations when yaw-ing. Go as high as possible

Important Functions in AC_PlatformerMovement

GetInputYaw: Calculates the necessary yaw to turn the pawn. Not necessary to be called from the outside

GetInAir: this pure function gets if the pawn is on the ground or in the air. Useful for Animation BPs

GetAttackState: this pure function will get the current EAttackState: NotAttacking, Jumping, HomingIn or Dash

GetGroundNormal: this pure function gets the normal of the ground. 0,0,1 when in air

GetVelocityToAdd: Delta velocity every tick of the movement component (reset to 0 at every start of tick and gets added with every velocity calculation during Tick)

SetInput: Feed the forward and right inputs to this function

SetTraceVector and GetTraceLine: the first function takes a vector in local space. The second calculates its world position to detect the ground

SetFrictionCoef, Ice and Underwater: calculates the friction coeficients. You want one of these for every surface type in your game and add it to the Velocity calculation graph

SetHomingTarget: feed a collision component to this (from an enemy, a jumper or anything you want) to set it as Homing Target then use the SetAttackState function to set the state to HomingIn

SetAttackState: sets to NotAttacking, Jumping, HomingIn or Dash. Always do a SetHomingTarget before setting to HomingIn

Bonk: Adds a physical impulse with a direction vector and force float. The jump event calls this function

DrawDebug: draws force lines, velocity, in air, attack state and homing target vector. You can delete debug things in shipping builds. Search blueprints for the bool Debug

Collision Types

There are 3 custom collision object types:

Enemy: Set this to every enemy collision component instead of Pawn. In a boss with many collision components, only the root one should do the platformer movement, but all of them should be set to Enemy if they can be attacked (see the Jump and Hit events on BP_PlayerPawn)

Query: set this to every invisible collision component and fire overlap events

Interactable: Set interactable actors to this type, see BP_Button

Interactables Interface

BPI_Interactables has two functions, Interact and Damage. In the example pawns, Interact is called on overlaps and Damage is called on hits. Implement BPI_Interactables on your pawns through Class Settings, then Call Interact or Damage (Message) to call them, and create the Events with the same name on the Actors that will respond.

See BP_PlayerPawn BP_Enemy and BP_Mine for examples of this, as mines will damage every pawn that implements the interface

Surface Types

The Platformer movement forces the Physical Material PM_Frictionless to be used so it can manually do rotations and velocity. So to do different surface types, it looks for different BPs of said surfaces.

To add a new surface volume type:

  • have any surface (it can be any kind of WorldStatic or Dynamic actor to be walked on)
  • in AC_PlatformerMovement, edit the SetSurface event and ESurfaces enumerator to add another surface type
  • Duplicate the SetFrictionCoef function and edit the friction multipliers, drift, yaw and forward forces
  • Add it to every Switch on ESurfaces graph like the others:
  • On the Volume Blueprint add an Overlap function like this:
  • Don’t forget to set the collision object type of your volume to Query
  • Test it to see if the static friction isn’t preventing the Pawn from moving. If it’s moving too slow or not at all, lower the static friction, or add more ForwardForce or lower the static friction speed

Notice that in these functions I’ve used fractions of the default friction variables and left those variables intact. This is important to be able to set them back to defaults in the default surface and also that’s why there’s an internal yaw, forward forces and max speed variables. If you change the defaults for a pawn, you’d have to change the defaults for every pawn to have the same movement (you can still make a pawn class that only moves in a specific surface with different default friction variables).

Known Issues


  • The pawn will stick to every surface angle which is undesirable in some situations
  • Camera needs rework during attacks
  • A rare bug may prevent the pawn from running at normal speed