How to set Up Tank Controls in Unreal Engine 5 (Tutorial)

Yasmin Curren
13 min readApr 18, 2024

--

In this tutorial I will get straight to the meat and ‘taters and show you how to replicate Tank Controls from nostalgic games such as Resident Evil and Silent Hill in Unreal Engine 5.

We will cover:

✨Independant Rotation
✨Turn Speed
✨Sprinting (Hold and Toggle)
✨Animations

Video version of this Tank Controls UE5 Tutorial

Set Up your Map to use a New Character and GameMode

Duplicate the Character Blueprint

Find BP_ThirdPersonCharacter and right click on it to find the option to duplicate. By working in a duplicate of the original character blueprint we ensure the original remains in tact in case we ever need to reference it again. Name the duplicate something like ‘BP_Character_Tank Controls’

Update your GameMode to use this New Character

Click on the Window drop down (top left) and enable the World Settings tab. In World Settings you can locate your GameMode which controls the rules of your game, including what character blueprint the player will reference. You can either create a Tank Control specific GameMode by duplicating BP_ThirdPersonGameMode and renaming it to something like ‘BP_TankControl_GameMode’ or update the original to use you’re new BP_Character_TankControls as your Default Pawn Class.

Set up the Tank Controls

Inside BP_Character_TankControls find the EnhanceInputAction IA_Move event (commented as Movement Input). You’ll find setup for Left/Right controls here and instead of it affecting the movement input we want to hook this into the players rotation. Delete the Add Movement Input node and replace it with a Set Control Rotation one referenced from the Player Controller. We can also delete the Get Right Vector node. Drag out from the New Rotation and select Make Rotator which will allow us to input rotation from each axis. From the remaining Get Control Rotation hook up the X and Y values to the corresponding X and Y values on your Rotator. However, from the Z value we will need to add the Action Value X before hooking this up to the Z value of the rotator because this is the axis we want to rotate on.

Make sure that Use Controller Rotation Yaw is enabled in the Details of you BP_Character_TankControls!

Also to make sure that the mouse does not change the rotation as well then simply unplug (or remove entirely) the EnhancedInputAction IA_Look logic as Tank Controls are usually used alongside Fixed Camera Angles so we do not need to give players control over the camera.

Press play and behold, now you have some basic Tank Controls. But let’s give you some more control on them shall we!

Control the Turn Speed

To enable you to control this turn speed independently, regardless of any other speed you set on your character for other movement, you can simply multiply the Action Value X from the Move Event by a float variable. Right click on this float variable to promote it to a parameter that you can change in the defaults panel. I find a variable if 3.0 works well for the turn speed.

Add Sprint (toggle or hold)

UE5 uses the Enhanced Input system. For this you can create each input mapping as an Input Action and then map it to keys within IMC_Default (Input Mapping Context). You can find the default Input Actions in Content > ThirdPerson > Input > Actions.

To allow our character to Sprint we need to create a new Input Action and name it IA_Sprint, leaving all of the original set up to default. We can then map this to our Shift key in the default InputMappingContext called IMC_Default (Content > ThirdPerson > Input). Add the IA_Sprint to the Mappings array and add the control binding that you want for the Sprint action (pressing the keyboard icon will automatially bind to any key press).

Once we have done this then we can go back into BP_Character_TankControls and add it as a new event. This new way of binding to keys using the Enhanced Input System allows us to have access to many different values such as when it has been pressed, released and even how many Seconds have elapsed since pressing the button.

The default player speed can be found in the player controller settings under Max Walk Speed.

To set up different speeds for running and walking we will need to Set this to different Floats depending on when the player has triggered Sprinting. Add two Float Variables for you to control these different speeds and name them: “SprintSpeed” with a Value of 600.0 and “WalkSpeed” with a value of 300.0.

For ease I would then create a new Function called ‘ToggleSprint’ to store the logic for switching between Walk and Sprint speed and a Boolean Variable called ‘IsSprinting’ to check whether the player is currently sprinting. Open the newly created function and click its node to and add a an Input of a Boolean called ‘ShouldSprint’ with a default Value of False, this will allow us to pass whether the character should sprint or not at the same time as calling the Toggle Sprint function. We can then check to see if Should Sprint is equal to Is Sprinting, if they are both the same then no action is needed, but if the they are different then we need can Set Max Walk Speed depending on the Value of the Boolean. You can do this easily by using the Select Float node and connecting the Should Sprint input value to drive whether the Sprint Speed or Walk Speed float should be picked. Don’t forget to then update the value of Is Sprinting once the Walk Speed has been set.

Make sure to EITHER update your default Max Walk Speed to be the same as your WalkSpeed variable or call Toggle Sprint with Should Sprint being False from Begin Play.

Hold Sprint: From the Triggered output Set the Max Walk Speed to use the SprintSpeed variable. From the Cancelled output set the Max Walk Speed to use the WalkSpeed variable.

Toggle Sprint: From Started call your Toggle Sprint Function and set the ‘Should Sprint’ input value to be the opposite of your ‘Is Sprinting’ boolean using the NOT node. Started will only trigger once while Triggered will be constantly.

To have control over the easing between both the walk speed and sprint speed then adjust the Max Acceleration and Braking Deceleration in the Character Movement Component.

Stop Sprinting when moving Backwards

Tapping back on the Directional Pad should automatically stop a sprint so we’re going to modify some of the setup we have just done to accomodate for this. To find out what direction the player is moving we can do a simple check to see if Action Value Y float from the EnhancedInputAction IA_Move is above or below 0. If it is above 0 then the player is walking forwards, if it is below 0 then the player walking backwards. We can store this information by right clicking on the Return Boolean node and Promoting it to a Variable, we can save this as ‘IsReversing’. Make sure this new Booleon is being set by the Greater than 0 check.

Hold Sprint:

For a Hold Sprint I want to ensure that the player is forced to walk when reversing, but seemlessly begins to run again after pressing forwards, even if the Sprint key has been held the entire time. Now that we know when the player is Reversing we can add a check to when the Sprint key has been Triggered. Because ‘Triggered’ gets called after one or more processing ticks it will check continuously so will know when the Sprint key is still being held. This way the Sprint speed will be toggled when the player walks backwards and again when they walk forwards, even if the key has been pressed the entire time.

Toggle Sprint:

For a Toggle Sprint I would expect a player reversing to cancel the sprint entirely until the Sprint button is pressed once more. So for this to happen I will add a Branch node after setting the boolean for ‘IsReversing’ and if true then call the Toggle Sprint function with Should Sprint being false.

Then we can disable the Sprint key from triggering our Toggle Sprint function by checking whether IsRevering is true before triggering the function. Is it is true then we stop the logic flow so that the player will continue to walk.

Set Up Turn Animations

Right now when the character turns there is no animation, it simply stands still and slides on the spot. To fix this we will use an animation that is readily available in the Unreal Engine 5 third person project called ‘MM_Walk_InPlace’.

Find the Animation Blueprint by searching for ABP_Manny (Content>Characters>Mannequins>Animations) and duplicate it, naming the duplicate something like ABP_TankControls so that we don’t lose the original reference. Then set up the BP_Character_TankControls to use this new Animation Blueprint by switching the Anim Class in the Details tab.

Now open up ABP_TankControls and drop down AnimGraphs from your MyBlueprints tab on the bottom right. Here you should see an Animation State Machine called Locomotion, double click this to open it up. Note how there are two States: Idle and Walk/Run. I’ll now show you how to add a new Animation State for TurnInPlace. If you click on the Transition in between these two states you’ll notice that the rule this transition uses is a Boolean called ‘ShouldMove’.

The logic behind this Boolean can be found in the Event Graph (Under Graphs in the My Blueprint Tab). When opening up the Event Graph you can see that there is already logic set up to check when a character ‘ShouldMove’. However, this boolean will only return true if the the character is accelerating, not if the player rotates without moving forward or backwards.

To check for if the player is rotating I will ‘Get Last Update Rotation’ from the Movement Component that gets set in the ‘Blueprint Initialize Animation’ Event, and right click on its return value to promote it to a variable called ‘CurrentRotation’. Now we have the initial rotation of the player when the animation has started.

Event Blueprint Update Animation gets called every frame the animation is updated so this is where we will check for if the player is rotating. The Sequence node executes a series of pins and generally keeps our Blueprints a bit tidier. Add a pin to this node for us to set up some Rotation check logic. From this new pin we can ‘Get Last Update Rotation’ again and check if this Return Value is not equal to (!=) our ‘CurrentRotation’ variable. Right click on the return value of this check and promote it to a Boolean Variable called ‘IsRotating’ that gets set based on the output of the check. We can then add a branch node to reset our ‘CurrentRotation’ Rotator variable if ‘IsRotating’ returns true.

Now that we know when the player is rotating we can navigate back to our Locomotion AnimGraph and right click to add a new State called ‘TurnInPlace’. Then click and drag from the ‘Idle’ state to the ‘TurnInPlace’ state to set up a new Transition Rule. By double clicked on the Transition Rule you can use the IsRotating Boolean to determine whether the state machine ‘Can Enter Transition’.

Set up the rest of the transitions so that when the character ShouldMove is False but IsRotating is True then transition to state TurnInPlace. When you are finished setting up your Transitions they should look like this:

To set up the animation to play when TurnInPlace is the active state double clicking on the TurnInPlace state to open it and right click to add MM_Walk_InPlace Sequence Player to the Output Animation Pose (you can search the animation name and choose the Play Sequence version of it).

Now click play and turn your character on the spot to watch it walk in place! If you need to debug this and see what active Animation State the player is currently in you can update the Preview Instance at the top of ABP_TankControls to use your active character while the game is running in PIE.

Using an Animation Blend Space to walk Backwards

The last bit of setup is to fix our player walking backwards as there is no animation for this at the moment. To create one right click on ‘MM_Walk_Fwd’ (or any other forward moving animation you want to create a backwards version of) and duplicate it, calling it ‘MM_Walk_Bwd’. In the Asset Details of this new Animation Sequence change the Rate Scale to -1. This will reverse any animation.

Now you have a bakwards walking animation, we need to include it into our walking animation used by the WalkRun Animation State. By default the Locomotion Animation State Machine uses ‘BS_MM_WalkRun’ for the Walk/Run state. This is a 1D Blend Space that blends between three animations (MM_Walk_InPlace, MM_Walk_Fwd and MM_Run_Fwd) based on the speed of the player. The speed is calculated from the Movement Components Velocity in the Animation Blueprint as the ‘GroundSpeed’ float variable. We will leave this logic as it is.

We will need to change animations based on both Speed and Direction so that the player can seamlessly walk both forwards and backwards. Because BS_MM_WalkRun is 1D we cannot add more than one axis to check against so we will create a new Blend Space by right clicking in your Content Browser and creating a new Animation > Blend Space using SK_Mannequin as your Skeleton. Name it something like ‘BS_MM_FwdAndBwdWalkRun’.

Upon opening this BlendSpace note that is has both a Horizontal and Vertical Axis on its grid at the bottom. In the Asset Details on the right name the Horizontal Axis ‘Direction’ with a Minimum Axis Value of -180 and Maximum Axis Value of 180. The closest to 0 on the Directional axis, the more the player was moving forwards, with both -180 and 180 representing moving backwards. Name the Vertical Axis ‘Speed’, keeping the Min and Max Axis Values the same as the default 1D BlendSpace: Maximum Axis Value: 500 (sprinting)and Minimum Axis Value: 0 (not moving).

Now you can click and drag any Animation Squence from within your Asset Browser on the right onto your grid. Line up the right Animation with the different points on the Axis, for example 0,0 would mean the player is not moving, so you can drop MM_Idle here. Once placing an animation into the grid you can click on it to change the axis values, either from the Blend Samples drop down in the Asset Details or directly at the top of the grid. Make sure MM_Idle sits at Direction: 0.0 and Speed: 0.0.

The placement of animtions that worked for me was this:

Hold CTRL while clicking and dragging around the graph to move the green axis and see a preview of the animations and how they blend with one another. To make these blends smoother you can increase the Weight Speed under Sample Smoothing in the Asset Details panel. I put mine to 5.0.

To be able to switch our ABP_TankControls Animation Blueprint to use this new Blend Space we will need to calculate the Direction in its Event Graph. After the ‘GroundSpeed’ variable gets set add a ‘Calculate Direction’ node and set the Base Rotation as our ‘CurrentRotation’ variable and Velocity as the ‘Velocity’ variable that was just Set. Right click and promote the output to a Float Variable called ‘Direction’.

Then go back into your Walk/Run Animation State in the Locomotion State Machine and replace the BS_MM_WalkRun Blendspace Player with your BS_MM_FwdAndBwdWalkRun, hooking up the ‘GroundSpeed’ variable to Speed and ‘Direction’ variable to the Direction input.

🎉Now you have Tank Controls set up and ready to use🙌

If you’d like to set up Fixed Camera controls use to use them with then check out my Fixed Camera Angle YouTube tutorial:

Fixed Camera Angle Tutorial

If there is anything that I have missed then please do share it with me, just like you I am constantly learning and sharing my findings in the hopes that I can continue to learn while helping others :)

I hope this was somewhat insightful and hopefully educational for you and I wish you the very best for your creative projects ❤

Download the Unreal Engine 5 project for the tutorial by becoming a Patreon and support my work (thank you so much).

If you’d like to check out more of my work or what I’m up to then you can follow me on YouTube, Twitch, Twitter or Instagram @YagmanX . I also have a free horror game ‘Perfection’ on itch.io and a music EP ‘Sweater’ available on all major music streaming platforms :)

--

--

Yasmin Curren
Yasmin Curren

Written by Yasmin Curren

Driven by Narrative, Inspired by Technology. YouTuber, Game Lover, Maker of silly creations with Code and Film! https://www.youtube.com/user/yagmanx

No responses yet