A first-person shooter (FPS) is a genre where the player uses guns and experiences the game through the eyes of a playable character. FPS games are immensely popular, with such well-known franchises as Call of Duty and Battlefield.
Unreal Engine was built to create FPS games, so it makes sense to create one using it. In this tutorial, you’ll learn how to:
- Create a first-person Pawn that can move and look around.
- Create a gun and attach it to the player Pawn.
- Shoot bullets using a line trace — also known as a raycast.
- Apply damage to actors.
Download the project materials with the Download Materials button at either the start or the end of this article, and unzip it. Navigate to the project folder called BlockBreakerStarter 5.0, and open BlockBreaker.uproject. You’ll see the following scene:
The green wall consists of multiple targets that turn red when they take damage. Once their health reaches zero, they disappear. The red button resets all the targets.
First, you’ll create the player’s Pawn.
Creating the Player Pawn
If you’re coming from UE4, you might’ve noticed that the folders panel seems to be missing. Despair not, as it’s hidden to allow an almost full-screen view of the project. To find the project folders, just click Content Drawer in the lower-left corner of the screen.
Now, you can see the navigation panel, complete with the folder structure and game assets. If you’d like to have it permanently open at the bottom of your screen, simply click Dock in Layout on the right of this panel.
Navigate to the Blueprints folder and right-click the panel background to create a new Blueprint Class. Select Character as the parent class and name it BP_Player.
Character is a type of Pawn with additional functionalities, such as the CharacterMovement component that automatically handles movement like walking and jumping. You simply call the appropriate function, and it moves the Pawn. You can also set variables such as walk speed and jump velocity within this component.
Before you can make the Pawn move, it needs to know when the player presses a movement key. To do this, you’ll map movement to the W, A, S and D keys.
Creating Movement Mappings
With key mapping, you can alter an attribute of the player character — such as their position in the X-Y plane or the camera angle of the viewport — and apply it in the game world. This is how you manipulate character displacement and viewing angle.
Select Edit ▸ Project Settings and open the Input settings under the Engine section.
Add two Axis Mappings by clicking the + next to Axis Mappings twice. You may have to expand the Axis Mappings list by clicking the expand triangle in front of Axis Mappings that appears after you add the first mapping. Rename them MoveForward and MoveRight. MoveForward will handle moving forward and backward. MoveRight will handle moving left and right.
For MoveForward, change the key to W by first selecting the None dropdown list. Then, expand the Keyboard list, and finally, select the letter W right at the bottom of that list.
After that, create another key by clicking the + next to MoveForward, and set it to S. Change the Scale for S to -1.0.
Later, you’ll multiply the scale value with the Pawn’s forward vector. This will give you a vector that points forward if the scale is positive. If the scale is negative, the vector points backward. Using the resulting vector, you can make your Pawn move forward and backward.
Next, you need to do the same for moving left and right. Change the key for MoveRight to D. After that, create a new key and set it to A. Change the Scale for A to -1.0.
Now that you have the mappings set up, you need to use them to move.
Double-click BP_Player to open it, and you’ll see the Viewport view. Navigate to the Event Graph using the tabs at the top of the window.
Right-click the view background to add a MoveForward event, the one listed under Axis Events. This event will execute every frame, even if you don’t press anything.
It also outputs an Axis Value, which is the Scale values you set earlier. It outputs 1 if you press W and -1 if you press S. If you don’t press either key, it outputs 0.
Next, you need to tell the Pawn to move. Add an Add Movement Input, and connect it like so:
Add Movement Input takes a vector and multiplies it by Scale Value, converting it to the appropriate direction. Since you’re using Character, the CharacterMovement component will move the Pawn in the appropriate direction.
Now, you need to specify which direction to move. Since you want to move forward, use Get Actor Forward Vector to return a vector pointing forward. Create one and connect it like so:
So, to summarize:
- MoveForward runs every frame and outputs an Axis Value. This value is 1 if you press W and -1 if you press S. If you don’t press either, it’s 0.
- Add Movement Input multiplies the Pawn’s forward vector with Scale Value. This causes the vector to point forward or backward, depending on which key you press. If you don’t press any key, the vector doesn’t have a direction, meaning the Pawn doesn’t move.
- The CharacterMovement component gets the result from Add Movement Input and moves the Pawn in the appropriate direction.
Repeat the process for MoveRight, but replace Get Actor Forward Vector with Get Actor Right Vector.
Before testing the movement, you need to set the default Pawn in the game mode.
Setting the Default Pawn
Click Compile in the window’s top-left corner, and go back to the main editor. Before you click it, it shows a yellow circle with a question mark. After clicking, it should have a green circle instead, showing that the process was successful.
Open the World Settings panel and locate the Game Mode section. Change Default Pawn Class to BP_Player.
Now, you’ll automatically use BP_Player when the game starts, and it’s placed automatically in the position of the Player Start asset. Press Play and use the W, A, S and D keys to move around. You may have to click the mouse inside the game window first to give that window the keyboard focus.
Next, you’ll create mappings for looking around.
Creating Look Mappings
Open Project Settings again. Create two more Axis Mappings called LookHorizontal and LookVertical.
Change the key for LookHorizontal to Mouse X.
This mapping outputs a positive value when you move the mouse right and vice versa.
Next, change the key for LookVertical to Mouse Y.
This mapping outputs a positive value when you move the mouse up and vice versa.
Now, you need to create the logic for looking around.
If a Pawn doesn’t have a Camera component, Unreal automatically creates a camera for you. By default, this camera uses the rotation of the controller.
Even though controllers are non-physical, they still have their own rotation. This means you can make the Pawn and camera face different directions. For example, in a third-person game, the character and camera don’t always face the same direction.
To rotate the camera in a first-person game, you just need to change the rotation of the controller. It’s pretty much the same process you did for movement — you just use rotations instead of translations.
Open BP_Player and create a LookHorizontal event.
To make the camera look left or right, you need to adjust the controller’s yaw. Create an Add Controller Yaw Input and connect it:
When you move the mouse horizontally, the controller yaws left or right. Since the camera is using the controller’s rotation, it also yaws.
Repeat the process for LookVertical, replacing Add Controller Yaw Input with Add Controller Pitch Input.
If you test the game right now, you’ll notice that vertical looking is inverted. This means when you move the mouse up, the camera looks down. If you prefer non-inverted controls, add a Multiply operator and multiply Axis Value by -1. This inverts Axis Value and controller pitching.
Click Compile, and then press Play. Use your mouse to start looking around.
Now that you’re done with movement and looking, it’s time to create a gun!
Creating the Gun
You know how when you create a Blueprint Class, you can select a parent class? Well, you can also select your own Blueprints as a parent. This is useful when you have different types of objects that share common functionalities or attributes.
Say you want to have multiple types of cars. You can create a base car class containing variables such as speed and color. You can then create children classes that use the base car class as a parent. Each child will also contain the same variables. Now, you have an easy way to create cars with different speed and color values.
You can use the same method to create guns. You just need to create a base class first.
Creating the Base Gun Class
Go back to the main editor, and create a Blueprint Class of type Actor. Name it BP_BaseGun, and double-click to open it.
Next, you’ll create variables to define the gun properties. To do that, go to the Variables section of the blueprint window, and click the + button on the top-right of the frame.
Create the following float variables:
- MaxBulletDistance: How far each bullet can travel.
- Damage: How much damage to apply when a bullet hits an actor.
- FireRate: How long before the gun can shoot another bullet, measured in seconds.
Now, you need a physical representation of the gun. Click Add, type Static Mesh, select the component Static Mesh to add it to the blueprint class, and name it GunMesh.
Don’t worry about selecting a static mesh now. You’ll do this in the next section when you create a child gun class. In this parent class, you just define that a gun must have a static mesh component that displays the gun geometry in the game.
Creating a Child Gun Class
Click Compile, and go back to the main editor. To create a child class, right-click BP_BaseGun and select Create Child Blueprint Class.
Name it BP_Rifle, and then open it. Open the Class Defaults at the top-right of the window, and set the variable values:
- MaxBulletDistance: 5000
- Damage: 2
- FireRate: 0.1
This means each bullet can travel a maximum distance of 5000. If it hits an actor, it deals 2 damage. When firing consecutive shots, the duration between each shot will be at least 0.1 seconds.
Next, you need to specify which mesh the gun should use. Select the GunMesh component on the left side of the screen, and notice that the Details tab on the right side has changed its contents. Look for the Static Mesh section and use the drop-down menu to set it to SM_Rifle.
The gun is complete. Click Compile, and close BP_Rifle.
Next, you’ll create your own camera component to give you better control of camera placement. It’ll also allow you to attach and keep the gun in front of the camera.
Creating the Camera
Open BP_Player, and add a Camera component the same way you created the Static Mesh component of the BP_BaseGun class. Name it FpsCamera.
The default position is a bit too low, which might make the player feel small. On the Details panel, set the location of FpsCamera to (X:0, Y:0, Z:90).
By default, Camera components don’t use the controller’s rotation. To fix this, go to the Details panel and enable Camera Options ▸ Use Pawn Control Rotation.
Next, you need to define the gun’s location.
Defining the Gun Location
To create the gun location, you’ll use a Scene component. These components are perfect for defining locations because they only contain a Transform. Make sure you have FpsCamera selected, and then add a Scene component to attach it to the camera. Name it GunLocation.
By attaching GunLocation to FpsCamera, the gun will maintain the same position relative to the camera, always keeping the gun in view.
Next, in the Details panel, set the location of GunLocation to (X:30, Y:14, Z:-12) to place it to the front and slightly to the side of the camera.
After that, set the rotation to (X:0, Y:0, Z:-95) to make it appear as though it’s aiming toward the center of the screen.
Now, you need to spawn the gun and attach it to GunLocation.
Spawning and Attaching the Gun
Locate Event BeginPlay on the BP_Player event graph, create and connect a Spawn Actor From Class to it. Set Class to BP_Rifle.
If you compile now, you’ll receive an error saying that the Spawn Transform node must have an input wired into it. This happens because, in the current form, this pin is a struct and needs proper initialization. To avoid this error, right-click Pawn Transform and select Split Struct Pin. This displays the variables that make up the pin and assigns initial values to them. Now the code compiles successfully.
Since you’ll need to use the gun later, you’ll store it in a variable, just as you created variables earlier for the base gun class. Now, create a variable of type BP_BaseGun, and name it EquippedGun.
By making the variable of type BP_BaseGun, you’re creating a big hole that can accept many shapes.
Next, set EquippedGun to the Return Value of Spawn Actor From Class.
To attach the gun, you use an AttachActorToComponent. Create one and set Location Rule and Rotation Rule to Snap to Target to make the gun have the same location and rotation as its parent.
Next, create a reference to GunLocation and connect everything:
So, to summarize:
- When BP_Player spawns, it spawns an instance of BP_Rifle.
- EquippedGun keeps a reference to the spawned BP_Rifle for later use.
- AttachToComponent attaches the gun to GunLocation.
Click Compile, and then press Play. Now, you’ll have a gun when you spawn! When you look around, the gun will always be in front of the camera.
Now comes the fun part: shooting bullets! To check if a bullet hits something, you’ll use a line trace.
A line trace is a function that takes in a start and end point, which form a line. It then checks each point along the line, from start to finish, until it hits something. This is the most common method in games to check if a bullet hits something.
Since shooting is a function of guns, it should go in the gun class rather than the player. Open BP_BaseGun and create a function called Shoot by clicking the + at the top of the Functions panel, on the left side of the screen.
After you enter the name of the Shoot function, UE5 should automatically open a blueprint tab for it on the center of the screen with a purple-colored Shoot node. If it doesn’t open automatically, double-click the newly created function on the left side panel.
Afterward, on the Input panel on the right side, click + to create two Vector inputs. Name them StartLocation and EndLocation to represent the start and end points of the line trace, which you’ll pass in from BP_Player. Notice that the Inputs are added to the Shoot node, just like function arguments.
You can perform a line trace using a LineTraceByChannel. This node checks for hits using the Visibility or Camera collision channel. Create one and connect it:
Next, you need to check if the line trace hit anything. Create a Branch and connect it:
Return Value outputs true if there was a hit and a false otherwise.
Next, to give the player visual feedback on where the bullet hit, you’ll use a particle effect.
Spawning Bullet Impact Particles
First, you need to get the location of the trace hit. Drag-click on Out Hit and release left-click in the graph. From the menu, select Break Hit Result.
This gives you a node with various pins relating to the result of the line trace.
Create a Spawn Emitter at Location and set Emitter Template to PS_BulletImpact. Then, connect its Location to Location of Break Hit Result.
Here’s the function so far:
So, to summarize:
- When Shoot executes, it performs a line trace using the provided start and end points.
- If there was a hit, Spawn Emitter at Location spawns PS_BulletImpact at the hit location.
Now that the shooting logic is complete, you need to use it.
Calling the Shoot Function
First, you need to create a key mapping for shooting. Click Compile and open Project Settings. Create a new Axis Mapping called Shoot. Set its key to Left Mouse Button, and then close Project Settings.
Next, open BP_Player, and create a Shoot event.
To check if the player is pressing the Shoot key, you just need to check if Axis Value equals 1. Create the highlighted nodes. One is a Branch, the other is an Equal operator:
Next, create a reference to EquippedGun, and then call its Shoot function.
Now, you need to calculate the start and end points for the line trace.
Calculating the Line Trace Locations
In many FPS games, the bullet starts from the camera rather than the gun, as the camera is already perfectly aligned with the crosshair. So if you shoot from the camera, the bullet is guaranteed to go where the crosshair is.
Still in the BP_Player Blueprint Class, create a GetWorldLocation (FpsCamera).
Next, you need to add a GetForwardVector to the FpsCamera. Click-drag from the FpsCamera and type getforwardvector.
Now, you need the end location. Guns have a MaxBulletDistance variable, so the end location must be MaxBulletDistance units from the camera. Click the EquippedGun variable and drag it into the blueprint graph, and click-drag out of this node. Then, type Max Bullet Distance, and select it in the window. To perform the mathematical calculations needed, click-drag from Max Bullet Distance, type * to create the multiplication node, click-drag from the multiplication node and type + to create the add node. The process should look like this:
Then, finalize by connecting the nodes:
After that, connect everything:
So, to summarize:
- When the player presses or holds left-click, the gun shoots a bullet starting from the camera.
- The bullet travels forward by the distance specified by MaxBulletDistance.
Click Compile, and then press Play. Hold left-click to start shooting.
Currently, the gun shoots in every frame. That’s too fast, so the next step is decreasing the gun’s fire rate.
Decreasing the Fire Rate
First, you need a variable to decide if the player can shoot. Open BP_Player and create a Boolean variable named CanShoot. Set its default value to true. If CanShoot equals true, the player can shoot and vice versa.
Drag the CanShoot variable into the blueprint graph and place a node to get its value. Click-drag from this variable, type AND, and select the corresponding logical operation. Change the Branch section to:
Now, the player can only shoot if the Shoot key is being pressed and CanShoot equals true.
After the gun shoots, it needs a cooldown time. So, you need to add some more nodes after the Shoot function. To do that, click-drag from the arrow on the Shoot function call, and type CanShoot to add a SetCanShoot node. Make sure to leave the checkbox on this node unchecked to set the variable to false. Next, click-drag from the SetCanShoot arrow, add a Delay node and a SetCanShoot node. Now, make sure the checkbox is checked to set the variable to true, allowing the next shot to be fired. Remember that the gun has a FireRate variable? Get the FireRate variable from EquippedGun the same way you got MaxBulletDistance. The final result should look like this:
You’ve just made the following changes:
- The player can only shoot if holding left-click and CanShoot equals true.
- Once the player shoots a bullet, CanShoot is set to false. This prevents the player from shooting again.
- CanShoot is set back to true after the duration provided by FireRate.
Click Compile, and then close BP_Player. Press Play, and test out the new fire rate.
Next, you’ll make the targets and button respond to bullets by applying damage to them.
In Unreal, every actor has the ability to receive damage. However, it’s up to you to decide how the actor responds to it.
For example, when receiving damage, a fighting game character would lose health. However, something like a balloon wouldn’t have health — you’d program it to pop when receiving damage.
Before you handle how the actor receives damage, you first need to apply damage. Open BP_BaseGun, and add an Apply Damage at the end of the Shoot function.
Next, you need to specify that the actor hit by the line trace should receive damage. Connect Damaged Actor to Hit Actor of the Break Hit Result.
Finally, you need to specify how much damage to apply. Get a reference to Damage and connect it to Base Damage.
Now, when you call Shoot, it will damage any actors hit by the line trace. Click Compile, and then close BP_BaseGun.
Now, you need to handle how each actor receives damage.
First, you’ll handle how the targets take damage. Open BP_Target, and create an Event AnyDamage. This event executes whenever the actor receives damage that’s not zero.
Next, call the TakeDamage function and connect the Damage pins. This subtracts health from the target’s Health variable and updates the target’s color.
Now, when the target takes damage, it loses health. Click Compile, then close BP_Target.
Next, you need to handle how the button takes damage. Open BP_ResetButton and create an Event AnyDamage. Then, call the ResetTargets function.
This resets all the targets when the button receives damage. Click Compile, and then close BP_ResetButton.
Press Play, and start shooting the targets. To reset the targets, shoot the button.
Where to Go From Here?
You can download the completed project files by clicking Download Materials at the top or bottom of the tutorial.
You now have an FPS base that you can easily expand on. Try creating more guns with different types of fire rates and damage. Maybe try adding reload functionality too!
We hope you enjoyed this tutorial, and if you have any questions or comments, please join the forum discussion below!