In this part of the tutorial, you will create an enemy NPC that detects, chases, and damages the player. In addition, the enemy will be able to receive damage and navigate around the environment to avoid obstacles using a Navigation Mesh.
First you will create the enemy logic using Blueprint Visual Scripting as with the previous tutorials. Then, you’ll create the Navigation Mesh to define the zones that AI Controller-possessed characters can navigate during gameplay.
Before You Begin
Make sure you understand these topics covered in the previous section of the Design a Puzzle Adventure:
Blueprints and Blueprint Functions
You’ll need the following assets from Create a Key:
BPL_FPGameBlueprint Function Library
Create NavMesh for the Enemy’s Navigation
Before you can add the enemy to a level and make it chase after the player, you have to build the NavMesh that the Enemy AI will use to navigate the level.
NavMesh is short for Navigation Mesh and it defines areas on the level that the AI can navigate within. By creating a NavMesh in this tutorial, you will define a zone in which the enemy can move to chase the player.
To add navigation mesh to your level, follow these steps:
In Unreal Editor’s Level Editor, in the Main Toolbar, click the Create button, go to Volumes and select Nav Mesh Bounds Volume. This creates a navigable zone for the AI in your project.
Using the Transform tools, move the NavMesh to intersect with the floor in your level.
Press P on your keyboard to toggle the debug view. Use this to view the NavMesh details in the level viewport — including the navigable zones on the level, as well as text-based debug information on the left-hand side of the viewport.
If you see a “NavMesh Needs To Be Rebuilt” message in the debug info, navigate in the Menu Bar to Build > Build Paths. This rebuilds your NavMesh.
Continue to move and scale (W and R keys on your keyboard) the NavMesh to modify the NavMesh bounds. Scale this volume up to your liking.
Ensure the bottom of the NavMesh is low enough to include any recessed floor pieces and that the top of the NavMesh is high enough to accommodate the height of the enemy.
If you’re using the tutorial sample level, create and scale two Nav Mesh Bounds Volumes so they fill Hallway 3 and Room 3.
As you scale and move the NavMesh, you will see the green zones expanding with the size of the bounding box — unless you have some obstacles, like cubes. Any parts that are cut-off in red mean that they are unnavigable by AI in your game.
If Unreal Editor is including anything in the NavMesh that it shouldn’t, select that mesh level object and disable Can Ever Affect Navigation in the Details panel.
Create an Enemy
You’ll create the enemy from the Character class since it already includes movement and animation features that make sense for a humanoid opponent. The Character class actually extends Pawn, which is the more general “controllable actor” used for things like vehicles, cameras, or non-humanoid creatures. For enemies shaped like people, Character is the better starting point.
Since you’re making this character from scratch, you’ll add a mesh to visually represent the enemy and play an animation using an Animation Blueprint. The Animation Blueprint is provided in the project files, so you will not create it by scratch, but it’s important to learn how you can integrate one with the enemy character’s Blueprint.
First, create the Enemy Blueprint. Follow these steps:
In the Content Browser, go to Content > AdventureGame > Designer > Blueprints > Characters.
Right-click anywhere that is empty in the Content Browser, and click Blueprint Class.
In the new window, select Character as the base class.
Name this class
BP_Enemy, and open it in the Blueprint Editor by double-clicking it.
When you create a Blueprint Class, you pick a parent class to build from. That parent already comes with built-in features. For example, when you made Blueprints from the Actor class, you started with a transform and the ability to hold components and run logic. Now, by starting from the Character class, you also get movement, collision, and animation support. You use the Base Class in a similar manner to a template. When you add functionality, you’re extending that base class.
With the BP_Enemy Blueprint Window open, enter the Viewport tab and take a look at the Components panel. You will see a Character Movement (CharMoveComp) component at the bottom of the list. All Character classes come with a Character Movement component. Click the component and look at the Details panel to see all the settings inside. You’ll override some of these settings as you create the enemies in your project.
Add a 3D Model to the Enemy
Your character also comes with a Mesh component, but instead of a static mesh, this component is a skeletal mesh. The static meshes you’ve been working with so far are fixed 3D models that don’t move, while a skeletal mesh has an internal skeleton so it can animate and deform.
First, set up the character’s mesh and animations. Follow these steps:
Select the Mesh component and look under the Details panel. Find the Mesh category and click the dropdown next to Skeletal Mesh Asset. In the list, search for the
SKM_Manny_Simplemodel and select it. This assigns the Manny model to the blueprint.In the Details panel, go to the Animation category. Click the dropdown next to Anim Class, and assign the
ABP_UnarmedAnimation Blueprint. Now, the enemy character should be playing an idle animation in the Viewport tab.Modify the animation blueprint to work properly with our enemy:
In the enemy mesh’s Anim Class property, click Browse to Asset in Content Browser next to
ABP_Unarmed.Double-click the
ABP_Unarmedanimation blueprint to open it.Go to the group of logic that comes after the Then 1 pin of the Sequence node.
You don’t want the acceleration check here to prevent the enemy characters from moving, so delete the wire between the And node and Set Should Move node.
Connect the Greater (>) node’s output pin to the Should Move pin, bypassing the acceleration check.
Compile, Save, and close the blueprint.
In the viewport, you can see a cylindrical capsule shape around the enemy character. This is a visual representation of the Capsule Component that detects collisions with other objects, including the ground. The character’s mesh is a more complex shape, so the simple collision cylinder smoothes out the shape for better collision detection performance.
The mesh is offset and not aligned with the capsule. To make the character’s Mesh line up with the Capsule Component, move the character down so the feet meet the bottom part of the capsule component.
To align the character mesh with its collision volume, follow these steps:
Select the Mesh component again to highlight the 3D model.
In the Details panel, use the Transform category’s Location field to change the Z axis, which is the last field with a blue color. Set the value to
-96.
Now both components are centered at the origin so the enemy does not float above the ground in the game.
Last, you’ll see the character has an Arrow Component (Arrow). The arrow indicates the front-facing direction of the blueprint. Make sure this arrow lines up with the direction the mesh is facing so the character runs in the correct direction.
To make the character mesh face forward, follow these steps:
Select the Mesh component again. Use the rotate gizmo or Transform category of the Details panel to rotate the character 90 degrees on the Z axis. Its last Rotation value should be -90.
Change the Material of the 3D Model
Before moving on to creating functionality, change the color of the enemy model to make it red. This distinguishes it from the player and make it look more like an enemy, instead of the current white color.
To make the enemy character a different color, follow these steps:
Under the Materials section in the Details panel, there are two elements:
MI_Manny_01_Newis the material that affects various places on the enemy model like the upper arms, legs, and head.MI_Manny_02_Newis the material that affects the forearms and torso.
Next to the Element 0, click the Browse in Content Browser button which looks like a folder and a magnifying glass. This opens the folder containing this material in the Content Browser. The second material,
MI_Manny_02_Newis in here too.Right-click the
MI_Manny_01_Newasset, and click Create Material Instance.Name the Material Instance
MI_Enemy_01and double-click on it to open it.In the Details panel, expand 01 - BaseColor, and enable the Paint Tint property.
Click the color swatch next to Paint Tint property and select a color. This tutorial uses Hex sRGB =
F60E6EFF.Click Save and close the window.
Back in the Content Browser, right-click
MI_Manny_02_New, and click Create Material Instance.Name this Material Instance
MI_Enemy_02and repeat the previous steps to change the color and save the asset.
Once you have repeated the steps, you should have two new material instances: MI_Enemy_01 and MI_Enemy_02.
Next, to assign these materials to the enemy character, follow these steps:
In the
BP_Enemyblueprint, in the Details panel, go to the Materials section.Click the dropdown for Element 0 and select the new material you created,
MI_Enemy_01.For Element 1, change it to the
MI_Enemy_02material.
Add an Enemy to the Level
Add an enemy to your level to see how it’s looking and behaving so far.
From the Content Browser, drag the enemy blueprint into the Level Viewport and place it in front of the player.
When you play the game, you should see the enemy animate with an idle animation.
Set Up the Enemy When Gameplay Starts
With the enemy ready visually, you can create the gameplay functionality. First, you’ll set up the enemy’s properties needed when they spawn.
To set the enemy’s movement speed when the game starts, follow these steps:
In the
BP_EnemyBlueprint Editor window, go to the EventGraph tab. By default, there are three events: Event BeginPlay, Event ActorBeginOverlap, and Event Tick. Select ActorBeginOverlap and delete it, as it is not necessary for this tutorial.Using the Components panel, drag the Character Movement component into the Event Graph. This creates a Character Movement node. With this component node, you can check or change properties in that component from the graph.
Drag the pin of the Character Movement node and create a Set Max Walk Speed node.
Right-click the green Max Walk Speed pin of the Set node and select Promote to Variable.
This creates a new variable in the My Blueprint panel, under the Variables list.
Rename this variable
Max Speed. Click the eye icon next to the variable to turn this into a public and editable variable.Change its Category to Setup.
Compile the blueprint, and in the Details panel, set Max Speed’s Default Value to
200.Always assign your editable variables a default value. If you forgot to change its value in the level editor, and the default value was 0, the enemy would not be able to move.
Connect Event BeginPlay to the Set Max Walk Speed node.
Next, two variables will track the enemy’s health. TotalHP, an instance-editable variable, sets the enemy’s starting HP. CurrentHP tracks how much health the enemy has during gameplay as they’re damaged by the player or environment.
To set the enemy’s HP, follow these steps:
In the Variables list, add a new variable called
CurrentHPof type Float.Drag the CurrentHP variable from the Variables list into the Event Graph and select the Set Current HP option. Drag the Exec pin of the Set Max Speed node and connect it to the Set Current HP node’s Exec pin.
On the Set Current HP node, right-click the Current HP float pin and click Promote to Variable.
Rename this variable TotalHP. Ensure its type is Float and click its eye icon to make it public and editable. In the Details panel, set its Category to Setup. Compile the blueprint and set the default value to
100.Connect the exec pins between the Set nodes.
You’ll be performing a lot of actions with the player character in this event graph, so next, save a reference to the player as a variable.
To set up a variable for the player character, follow these steps:
In the Variables list, create a new variable named
PlayerRefand change its type to Character (Object Reference).Creating a reference variable for the Character Object is better for your project’s performance than calling the Get Player Character function each time you need to reference the player.
After the Set Current HP node, connect a Set PlayerRef node.
For its Player Ref input pin, connect a Get Player Character node. Ensure the Player Index value is 0. This is the default index for the first player character spawned into the level.
Make the Enemy Chase the Player
Next, you’ll create the logic for moving the enemy towards the player. You can do this by creating a Custom Event. Call custom events from anywhere in the blueprint to trigger and execute some logic.
To create a custom event that triggers a move action, follow these steps:
Right-click anywhere in the event graph and enter
Custom Eventin the search field. Click the Add Custom Event option in the list and name this event MoveToPlayer.Drag the pin of the MoveToPlayer event node and search for and create an AI MoveTo node. This node is an action that pawns with an AI Controller use to move to a specific location. In this case, you will use it to move the enemy to the player.
On the AI MoveTo node, drag the Pawn pin and enter
Selfin the search field. Select Get a reference to self to create a node that refers to the actor of this blueprint in-game.Drag the Target Actor pin of the AI MoveTo node and create a Get PlayerRef node.
Set Acceptance Radius to
10. This is the distance in centimeters at which the enemy considers itself to have arrived at its destination. It gives you more control than Stop on Overlap.
In this case, you are using the Self node to define this enemy as the Pawn that should move. Then, you set the player as the Target Actor, which is the target the Pawn moves towards.
The AI MoveTo node comes with On Success and On Fail events. These define what happens if the enemy reaches the player, or if it fails.
To define what happens after the enemy moves, follow these steps:
In the AI MoveTo node, drag the On Success pin and create a Delay node.
Right-click the Duration pin from the Delay node and select Promote to Variable.
Name this variable WaitAtDestination and ensure its type is Float.
Compile the blueprint and change WaitAtDestination’s default value to
5. Click its eye icon to make it editable, and change its Category to Setup.In the Event Graph, drag the Delay node’s Exec pin and create a Move To Player node. This ensures the enemy continues to chase the player if they move away, but after a delay that gives the player a chance to gain some distance.
From the AI MoveTo node, drag the On Fail pin and create a new Delay node.
Drag the Completed pin of the Delay and create a Move To Player node. Leave the Duration at 0.2. This ensures the enemy keeps moving if they haven’t reached the player yet.
In the Event BeginPlay group of logic. At the end of this sequence, after the Set Player Ref node, connect a Move To Player node to trigger this event. This gets the enemy moving at the start of the game so you can test the enemy’s movement.
Save and Compile the blueprint.
Your event graph should now look like this:
Test Enemy Movement
In your level, move your enemy actor to be within the bounds of the NavMesh, meaning on the green zones.
Select the BP_Enemy actor in the Level Viewport or the Outliner. In the Details panel, you will see the variables you have added in the blueprint in the Setup section. You can change these values to fit your project’s needs, or turn on Debug Detection to enable the debug drawing of the line trace.
Play your level again and see how the enemy behaves now. It should walk towards the player, stop when it reaches the player, wait 5 seconds, and then try to walk towards the player again.
If anything doesn't work as intended, check if the variables you have created in the blueprint have correct values set in the BP_Enemy in the scene. If you don’t set the values of the Max Speed, or the Max Detection Distance, the enemy will not move. The same thing might happen if the values are too low.
Deal Damage to the Player
Now that the enemy can reach the player, you can add functionality that makes the enemy damage the player when they collide. In this tutorial, you’ll create an enemy that self-destructs on contact with the player, so you’ll also add logic to remove that enemy after it damages the player once.
To check if the enemy has collided with the player, follow these steps:
In the Components panel, right-click Capsule Component (CollisionCylinder), go to Add Event, and select Add OnComponentHit.
This creates a new event node in the Event Graph that executes when the Capsule Component hits something.
Drag the pin of the On Component Hit node and create a Branch node.
Connect the Condition pin to the Other Actor pin of the On Component Hit node, which prompts you to create a new node.
Create an Equal node. Drag out the Select Asset pin of the Equal node and add a reference to the PlayerRef variable.
Now, this logic triggers an event when the enemy’s Capsule Component hits something in the game. The event checks if the Capsule Component hit the player character.
To deal one hit of damage to the player and remove the enemy, follow these steps:
In the Variables list, create a new variable named Eliminated and change its type to Boolean. You’ll use this when the enemy is defeated and should be removed from the game.
To ensure they only damage the player once, drag off the Branch node’s True pin and create a Do Once node.
From the Do Once node’s Completed pin, create an Apply Damage node. Drag the Damaged Actor pin and connect a reference to the PlayerRef variable. This is the actor who should receive the damage.
Right-click the Base Damage pin and select Promote to Variable.
In the Variables list, click Base Damage’s eye icon to make it editable, and change its Category to Setup. Compile the blueprint and set the default value to
25.Drag the Eliminated variable from the Variables list into the Event Graph and select Set. In the node, click the checkbox to set Eliminated to true.
Connect the Exec pin of the Apply Damage node to the Set Eliminated node.
Drag the Exec pin of the Set Eliminated node and create a Delay node. Set the Duration to
2.0.Drag the Exec pin of the Delay node and create a Destroy Actor node. The Target property should be set to self by default.
When the enemy collides with the player, it applies damage to the player and kills the enemy after a 2-second delay.
Now, the enemy can run towards the player and then apply damage and self-destruct when it collides with the player. However, it does not consider the distance or obstacles between the player and the enemy. So the enemy always chases the player no matter the distance or line of sight.
BP_Enemy’s finished On Component Hit logic should look like the following:
To copy the blueprint snippet below into your BP_Enemy event graph, ensure your variable names match those in the sample project.
Add Distance and Obstacle Logic
Next, add a maximum detection distance so the enemy can only detect the player when they are close enough to the enemy. Then, finish by implementing enemy line-of-sight restrictions so they can’t see the player through walls.
To do this, you’ll first create a new function in your blueprint library that performs a line trace between the enemy and the player.
Calculate Line of Sight and Distance With a Line Trace
A Line Trace (or raycast) is a common practice in game development. Line Traces draw an invisible line from a point in the world (like a source actor) to see what the line hits. It’s often used to detect objects or surfaces at runtime so you can trigger logic depending on the result of the trace.
In this tutorial, you’ll cast a line trace from the enemy character to detect when the player character is in the enemy’s line of sight.
For more information about Line Traces, see the Traces with Raycasts documentation.
To set up a function that uses a line trace to find the player, follow these steps:
In the Content Browser, go to your Core folder and open the
BPL_FPGameblueprint library.Add a new function named
fnBPLFindPlayer.In the new function’s Details panel, in the Inputs section, click Add (+) to create the following inputs:
Player Reference (Pawn Object Reference)
Start Location (Vector)
Max Detection Distance (Float)
Debug (Boolean)
After adding these inputs, the fnBPLFindPlayer function entry node now has corresponding pins for each of the variables.
In the function’s Details panel, in the Outputs section, click Add (+) to create a Boolean-type output value named Found.
After adding the Found output, a new Return Node appears in your graph with the Found pin.
In the My Blueprint panel, in the Local Variables section, click Add (+) to create a local variable named PlayerFound with type Boolean. Ensure its default value is false.
The player reference is critical for the function to execute properly, so when the function starts, check for a valid player reference to avoid errors.
To check for valid input, follow these steps:
Delete the wire between the entry node and Return Node by holding Alt and clicking the wire or either exec pin.
After the function entry node, create and connect an Is Valid node.
Ensure you create an Is Valid node represented with a question mark (?) icon near the bottom of the node actions list.
Connect the Player Reference pin from the entry node to the Input Object pin on the Is Valid node.
Connect the Is Not Valid exec pin to the Return Node.
For the Found return value, connect a reference to the PlayerFound variable. This exits the function, returning PlayerFound=False back to the enemy’s event graph.
If the player is valid, the function should execute the line trace object, then return PlayerFound.
To set up the line trace, follow these steps:
From the Is Valid exec pin, add a Sequence node to organize your logic.
Drag off the Sequence node’s Then 0 pin and add a Line Trace By Channel node.
Line Trace By Channel detects objects on a specific collision channel. To view collision channel settings for a blueprint, select the blueprint’s collision component, and go to the Collision > Collision Presets properties in the Details panel. The Trace Responses section has Visibility and Camera channels.
From the function entry node, drag the Start Location pin and connect it to the Line Trace By Channel node’s Start pin. This sets the enemy character’s location as the starting point for the line trace.
To keep your graph tidy, create a Get Player Reference node. The f icon in the top-right corner of the node shows it’s a function input. You can add references to these inputs like you would any other variable.
Drag off the Player Reference pin to a blank spot in the graph. This opens the node actions list. In the list, search for and create a Get Actor Location node.
Connect its Return Value to the End pin of the Line Trace node. This ends the line trace at the player’s location.
On the Line Trace By Channel node, set the Trace Channel property to Camera using the dropdown menu.
Now that you’ve set where the line trace begins and ends, define what happens when the trace hits something.
To check if a line trace has hit the player, follow these steps:
Drag off the line trace’s Out Hit pin and add a Break Hit Result node. When a line trace hits an object, a lot of information is collected. You only need to use a few specific values, so a Break Hit Result node is needed to split the data into the individual components of the returned data.
In the Break Hit Result node, click the arrow at the bottom to see more options.
You want to know if the player is in line of sight and within a certain distance of the enemy, so you’ll use the Hit Actor pin to check for the player, and use Trace Start and Trace End to measure the distance to the hit object.
Drag off the Hit Actor pin and add an Equal operator node. For the bottom input, connect a reference to the Player Reference function input.
To reference function input values, you can add a Get node similar to other variables.
Create a Distance (Vector) node. Connect V1 to Trace Start and connect V2 to Trace End.
A vector is a set of X, Y, and Z values that represent an object or point’s position in 3D space. The Distance node calculates the distance between two of these points, which results in a float value.
Drag off the Distance node’s Return Value and add a Less (<) node. For the bottom input, connect a reference to the Max Detection Distance function input.
Create an AND (Boolean) node.
Connect both the Equals (==) and Less (<) nodes’ boolean output pins to the AND node’s input pins.
With this logic, the AND node returns true if the line trace hits an actor that’s equal to Player Reference, and the distance between the start of the trace (the enemy) and the end (the hit object) is less than Max Detection Distance.
To use the trace result to set and return PlayerFound's value, follow these steps:
Drag off the AND node’s output and add a Branch node.
Connect its exec pin so it executes after Line Trace By Channel.
From the Branch node’s True exec pin, create a Set variable node to set the local PlayerFound variable to true.
From the Branch node’s False pin, create a Set PlayerFound variable. Keep the value false.
You’re finished with the line trace logic, so go back to the Sequence node and connect its Then 1 pin to the Return Node to exit the function and send the PlayerFound result back to the enemy blueprint.
Add a Line Trace Debug Option
You want to be able to easily toggle a debug visual of the line trace on and off from the level editor. However, the Line Trace node only lets you pick one option from the Draw Debug Type list. You can use a Select node to make the debug type editable in the level editor.
To set up a customizable debug option to the line trace, follow these steps:
Drag from the Line Trace By Channel node’s Draw Debug Type pin and create a Select node.
Connect the Select node’s Index pin to a reference to the function’s Debug input.
The Select node’s index is a wildcard, so when you connect the boolean-type Debug value, the options change to False and True.
Set the False option to None. Set the For Duration option to True.
At the bottom of the Line Trace By Channel node, click the arrow button to see more options. Change the Draw Time to
0.1seconds.Save and Compile your Blueprint Function Library.
This logic uses the Debug variable to determine if the Line Trace debug drawing is active or not:
When the Debug variable is false, the Draw Debug Type is set to None, meaning no debug drawing is rendered.
When Debug is set to true, the Select node changes the Draw Debug Type to For Duration, which renders the line trace at runtime for a set duration.
The finished fnBPLFindPlayer function should look like the following:
If you copy this blueprint snippet into your project, you’ll need to connect the function entry node’s Exec and Player Reference pins to the Is Valid node’s Exec and Input Object pins. For the snippet to copy properly, ensure the names of your function inputs match those in the sample project.
Update the Move-to-Player Logic
Now that you can call a function that looks for the player while considering distance and line of sight, add logic to the enemy that makes them look for and chase the player only on sight, or when the line trace successfully finds the player.
To make the enemy chase the player after finding the player, follow these steps:
Go back to the
BP_Enemyblueprint. In the Event Graph, find the provided Event Tick node.Drag the Exec pin of the Event Tick node and create a Branch node.
The On Tick event runs every frame while the game is playing. Use it to make the enemy constantly check for the player’s position and determine whether to start chasing.
Drag the Condition pin of the Branch node and create a NOT Boolean node, which returns the inverse of a boolean’s value.
In this case, you want to negate the Eliminated variable, so drag the input pin of the NOT node and search for Get Eliminated.
This checks if the enemy is not eliminated before proceeding with the True pin of the Branch node.
Drag the True pin of the Branch node and create a FnBPLFindPlayer node. This node performs a line trace to find the player in the world and checks the current distance between the enemy and player.
On the Fn BPLFind Player node, make these following connections using its pins:
Player Reference: Connect a reference to the PlayerRef variable.
Start Location: Create a Get Actor Location node with the Target property set to self. This assigns the start location of the line trace to the enemy’s position in the world.
Max Detection Distance: Right-click the pin and select Promote to Variable. Click its eye icon to make it editable, and change its Category to Setup. Compile, and set its Default Value to
20000(200 meters). The smaller this value is, the closer the player has to be for enemies to detect them.Debug: Select Promote to Variable and name it
DebugDetection. Also make this variable editable and appear in the Setup category.
If the player is found by the line trace, set the maximum movement speed of the enemy to a desired amount, moving the enemy towards the player. If not, you should set the speed to 0 so the enemy can’t move towards the player.
To make the enemy move when the player is found and stop when the player is not found, follow these steps:
In the FnBPLFindPlayer node, right-click the Found pin and select Promote to Variable. This automatically connects a Set node for that new variable. Now you can use this Found result elsewhere in the graph.
After the Set node, connect a Branch node. Drag the Condition pin of the Branch node to the Set Found node’s output pin.
From the Components panel, drag the Character Movement (CharMoveComp) into the Event Graph. Drag its pin and create a Set Max Walk Speed node.
Drag the True pin of the Branch node and connect it to the Set Max Walk Speed node.
For the Set node’s Max Walk Speed pin, connect a reference to the Max Speed variable.
After the Set node, connect a MoveToPlayer node to call that event and make the enemy move only if they’ve found the player.
Duplicate the Set Max Walk Speed and Character Movement nodes. Connect the False pin of the Branch node to the new Set node.
In the second Set Max Walk Speed node, ensure the walk speed value is 0. This makes the enemy stop moving without canceling its AI MoveTo task and needing to run the task again.
Now that you have the enemy looking for the player every frame, delete the Move to Player node that you added at the end of the Event BeginPlay logic. This node was useful for testing a partially-completed enemy, but you don’t need it anymore.
Go to your MoveToPlayer event logic. Now, you only want the enemy to execute this if the player was found:
Drag off the MoveToPlayer node and create a Branch node.
For the Branch’s Condition, add a reference to the Found variable.
Now, If the player is within the given distance to the enemy, and there are no obstacles in between the two, the enemy’s movement speed will be set to the MaxSpeed variable and they’ll execute the MoveToPlayer logic. If either of those conditions are not met, the enemy’s movement speed will be set to 0 — blocking the enemy from moving towards the player.
BP_Enemy’s final variable list should look like the following:
To copy the blueprint snippets below into your BP_Enemy event graph, ensure your variable names match those in the sample project.
BP_Enemy’s final Event BeginPlay logic should look like the following:
BP_Enemy’s final MoveToPlayer logic should look like the following:
BP_Enemy’s final Event Tick logic should look like the following:
Allow Enemies to Receive Damage
Before finishing up this blueprint, you need to make sure that the enemy can be damaged as well. If you continue working on your game beyond this tutorial series, you may want enemies to be damaged by the traps or give the player an equippable item that can damage and eliminate enemies.
To make enemies take damage, follow these steps:
Right click anywhere in the Event Graph and create an Event AnyDamage node.
Drag the exec pin from Event AnyDamage and create a Set CurrentHP node.
To subtract the damage dealt from the CurrentHP, drag the Current HP property’s pin and create a Subtract node.
Drag the upper pin of the Subtract node and create a Get Current HP node.
Connect the bottom pin of the Subtract node to the Damage property of the Event AnyDamage node.
When any damage is dealt to this actor, this takes the CurrentHP variable’s value and subtracts the Damage from it, and then sets the CurrentHP value to the new value.
Next, check if the CurrentHP is less than or equal to 0, which should eliminate the enemy.
To remove the enemy when its HP is 0, follow these steps:
Drag the Set node’s pin, and create a new Branch node.
Drag the Condition pin of the Branch node and create a Less Equal (<=) node.
Connect the Set Current HP node’s output pin to the Less Equal node’s upper input pin. Make sure that the lower pin is set to 0.
Drag the True pin of the Branch node, and create a Do Once node.
Drag its Completed pin and create a Set Eliminated node. In the Set node, toggle the Eliminated property to true.
After the Set node, connect a Delay node with the Duration set to
2.Drag the Completed pin of the Delay node and create a Destroy Actor node with the Target property set to self.
Save and Compile the blueprint.
BP_Enemy’s finished Event AnyDamage logic should look like the following:
Test the Finished Enemy Character
If you now play the game, depending on the distance between the enemy and the player, the enemy might not be moving. If you move closer to the enemy, it should start chasing the player.
Try it with an obstacle. Exit play mode and add a blockout cube or wall in the middle of the NavMesh zone by pressing the Create button in the Main Toolbar and selecting Shapes > Cube. This obstacle cuts into the NavMesh.
If the player starts behind this obstacle, the enemy won’t be able to chase the player since the linetrace is blocked by the cube, resulting in the enemy failing to find the player. If the player walks around the cube and the enemy has direct sight of the player, it starts chasing the player. Once the enemy starts its AI MoveTo action, hiding behind an obstacle won’t stop the enemy’s pursuit.
Placing Enemy Locations in Your Project
For our sample level, we placed several enemies in Hallway 3 and Room 3. The first enemy is alone in Hallway 3 to give the player a simple first encounter and help them learn the enemy character’s behavior and abilities. After encountering the single enemy in the hallway, we placed two additional enemy characters in Room 3 to introduce more of a challenge to the player.
You can vary enemy numbers and types to provide different levels of difficulty throughout your project. Introducing players to new enemies and challenges slowly creates a balanced difficulty curve that the player can become accustomed to over time. Creating a difficult enemy encounter after allowing the player to learn how to navigate and defeat enemies provides a challenge that can feel rewarding to the player.
Next Up
In the next module, you will learn how to add a sprint mechanic to the player’s moveset. This helps the player move through familiar places in the level and also gives them a tool to avoid the enemies you just added to the project.
Add a Sprint Mechanic to the Player
Use Input Actions to add a sprint mechanic to the player character's move set.