Tuesday, April 16, 2024
HomeSample Page

Sample Page Title


Relying on the kind of enemies you may have in your sport, you’ll create totally different AI habits. And there are a number of methods methods to create enemy AI in Unreal Engine, from the essential enemies that transfer between two factors all the best way to creating complicated AI habits utilizing Conduct Timber and Blackboards.

On this put up we’re going to study AI in Unreal Engine by creating primary, intermediate and superior enemy AI habits utilizing C++ and blueprints.

Obtain Property And Full Venture For This Tutorial

Unreal Engine Enemy AI C++ And Blueprints Tutorial

.single-product div.product .abstract kind.cart { show: none!necessary; }

Class: Uncategorized

To comply with together with this tutorial, please obtain the starter mission by clicking on the inexperienced Obtain belongings button above.

Within the downloaded folder you will discover the completed mission, and the starter mission which I ready so that you can comply with this tutorial. 

Necessary Info Earlier than We Begin

One of many labels for this tutorial is newbie, nonetheless this isn’t a tutorial for full newbies.

I count on you to know methods to create primary video games in Unreal, however you’re a newbie in the case of AI programming in Unreal. So it’s necessary that you know the way to code in C++ and blueprints, and know methods to use Unreal and its interface.

One other factor to notice is that I’m utilizing Unreal Engine 4.27 for this tutorial, however the methods that I’m going to show you will be utilized to any Unreal Engine model.

Enemy AI Patrol

First we’re going to create a primary patrol habits for the enemy the place the enemy goes to roam within the degree.

Open the Enemy_AI_Starter_Project that you just downloaded. Open the EnemyAI_Map positioned in Content material -> Maps folder. Within the map you’ll discover the enemy and the participant actor are already ready.

Open the BP_Enemy blueprint positioned in Content material -> Blueprints folder. Within the Occasion Graph tab, Proper Click on and seek for customized occasion:

Img 1

Identify the brand new customized occasion Random Patrol:
 

Img 2

To make the enemy patrol within the degree, we’re going to use AI MoveTo perform, and we’re going to present it a random vacation spot inside the navigationable bounds quantity:

Img 3

You possibly can copy the nodes from right here:

For AI MoveTo parameters we supplied self, which is a reference to the enemy blueprint, and for the vacation spot we used the GetRandomReachablePointInRadius which is a perform that can give us a reachable level within the radius we offer from the origin.

This perform will calculate all of the collisions which might be in the best way of the AI and that method the enemy will cleverly keep away from any obstacles in his path.

For the origin parameter of the GetRandomReachablePointInRadius perform we supplied the situation of the enemy, as a result of we’re going to patrol from the enemy’s location.

For the radius I’ve set 1500 as the worth, which suggests it should attempt to get a reachable level from the enemy’s location within the 1500 worth radius. In fact, we are able to change the radius worth to the next or a decrease quantity anytime we need to make the enemy patrol additional within the degree.

When the AI MoveTo perform finishes, we’re going to delay for 1 second utilizing the Delay perform, after which name the Random Patrol node we create in order that the enemy will randomly patrol the extent once more.

Earlier than we proceed to check this out, from the BeingPlay name the Random Patrol node we created:

Img 4

Compile and save the modifications we made within the BP_Enemy blueprint. In an effort to make this work, we have to add the NavMeshBoundsVolume within the degree. From the Place Actors tab, seek for the NavMeshBoundsVolume:
 

Img 5

Drag the NavMeshBoundsVolume within the degree and set the next values for its Location and Scale:

Img 6

This may make the NavMeshBoundsVolume cowl the entire degree and this would be the navigationable space the place the enemy can transfer with the assistance of AI MoveTo perform:

Img 7

Allow us to now run the sport and check it out:

We are able to additionally take away the delay that occurs after AI MoveTo perform finishes which can make the enemy patrol the extent with out stopping.

Detecting The Participant’s Presence And Transferring In direction of Him

We are able to use the identical perform to make the enemy run in the direction of the participant. However first, we’d like a option to detect the participant’s presence close to the enemy. For that we’re going to connect a Sphere Collision part to the enemy.

Within the blueprint editor for the BP_Enemy, within the Parts tab click on on Add Element and filter for sphere collision:

Img 8

Rename the part to Participant Collision Detection and within the Particulars tab set the Sphere Radius to 800:
 

Img 9

Within the My Blueprint tab, below variables create a brand new boolean variable and identify it Participant Detected. Then create one other variable and for the variable sort, click on on the variable icon:

Img 10

Within the search bar filter for third individual and choose the Object Reference for the Third Individual Character:

Img 11

On this variable we are going to retailer a reference to the participant actor since we’d like his location with a purpose to make the enemy transfer in the direction of him.
 
For that, we have to choose the Participant Collision Detection part within the Parts tab, and within the Particulars tab scroll all the best way to the underside and below Occasions, click on on the inexperienced + button for On Element Start Overlap and On Element Finish Overlap:
 

Img 12

With these two capabilities we’re going to detect when the Participant Collision Detection sphere collides with the participant actor in order that we are able to chase him, and when the participant actor exists the collision in order that we are able to cease chasing him.

However earlier than we try this, we’re going to create a customized occasion and identify it Transfer To Participant, which goes to make the enemy transfer in the direction of the participant actor:

Img 13

You possibly can copy the nodes from right here:

As you may see, we’re utilizing the Participant REF variable, which is a reference to the participant actor within the sport, to get the situation of the participant and make the enemy transfer in the direction of him.

The Acceptance Radius parameter for the AI MoveTo perform is how removed from the goal will the AI cease transferring, on this case we set the worth to 150 models.

To get a reference to the participant actor, we have to detect collision in On Element Start Overlap that we created:

Img 14

In OnComponentBeginOverlap we first carry out a solid to check if the participant actor has collided with the sphere, if that’s true, we are going to get a reference to the participant actor and we set the Participant Detected bool worth to true. We are going to use this variable to manage the enemy AI logic.

After which, we make the enemy go in the direction of the participant utilizing the Transfer To Participant customized occasion node we created.

In OnComponentEndOverlap, when the participant actor collides with the sphere, we’re going to set the Participant Detected worth to false, and make the enemy patrol randomly once more:

Img 15

You possibly can copy the nodes from right here:
 

Compile and save the modifications and now let’s run the sport and check it out:

Whereas the enemy is detecting the participant’s presence and going in the direction of his location, now we have one massive subject, and that’s the enemy just isn’t following the participant when he strikes round, as a substitute it goes in the direction of the primary location the place the participant was after we detected the collision with the participant.

We are able to repair this subject by calling the Transfer To Participant within the Tick occasion, however this may make an issue after we need to assault the participant. As a substitute there’s a higher resolution to this downside that we’re going to implement now.

A Smarter Approach To Make The Enemy AI Chase The Participant

Because the AI MoveTo perform will transfer the AI to the primary place we go to it, we’d like a option to take a look at if the goal place has modified in order that the AI will transfer in the direction of the modified place.

For that, I’m going to create a brand new customized occasion, identify it Search participant and add the next nodes to it:

Img 16

You possibly can copy the nodes from right here:
 

Search Participant will name the Transfer To Participant which makes the AI transfer in the direction of the participant goal, however it should additionally use the Set Timer By Perform Identify to name the Search Participant after each 0.25 seconds.
 
We specified that within the Perform Identify parameter the place we handed the Search Participant, and for the Time parameter we set 0.25. Additionally, the Looping parameter is about to true, which suggests the Set Timer By Perform Identify might be known as again and again after each 0.25 seconds.
 
Earlier than we proceed, we’re going to create one other customized node that can make the AI cease in search of the participant:
 

Img 17

You possibly can copy the nodes from right here:

The Clear Timer By Perform identify will cease the timer from calling the perform with the required identify, in our case Search Participant which we supplied within the Perform Identify parameter.

We have to do that as a result of we specified that the Set Timer By Perform Identify ought to loop, which suggests it should run on a regular basis till we cease it through the use of Clear Timer By Perform Identify.

Now, we have to edit the Transfer To Participant perform:

Img 18

You possibly can copy the nodes from right here:
 

Now, when the enemy reaches the participant, it should take a look at if the participant continues to be inside its bounds by checking if the Participant Detected worth is true, if that’s the case it should proceed chasing the participant by calling Search Participant.
 
We additionally want to vary the On Element Start and Finish Overlap for the enemy:
 

Img 19

You possibly can copy the nodes from right here:

Compile and save the brand new modifications to the BP_Enemy blueprint and let’s run the sport to check it out:

As you may see now, even when the participant modifications his location the enemy is consistently chasing him.

Enemy AI Assault

Now that now we have the chase logic in place, we are able to create the assault performance of the enemy.
 
First we’re going to create a brand new boolean variable and identify it Can Assault Participant, we’re going to use this variable to manage the assault logic of the enemy.
 
Subsequent, with a purpose to detect if the participant is within the assault vary of the enemy, we’re going to create a brand new Sphere Collision part. Identify the brand new Sphere Collision to Participant Assault Collision Detection and within the Particulars tab set the Sphere Radius to 200:
 

Img 20

For the Occasion Graph, we’d like the On Element Start and Finish Overlap for the Participant Assault Collision Detection:
 

Img 21

The thought is after we detect participant collision with the Participant Assault Collision Detection part, we are going to set the Can Assault Participant worth to true, and when the participant exists that collision we are going to set the worth to false:

Img 22

You possibly can copy the nodes from right here:
 

We additionally must make modifications within the Transfer To Participant node in order that the enemy assaults the participant when it will get near him. First we’re going to create a brand new situation when the AI MoveTo finishes:

Img 23

When the enemy will get to the participant’s location we’re going to test if the enemy can assault the participant, if that’s true we are going to name Cease Searching for Participant as a result of now we have to assault him, if the enemy can’t assault the participant, then we are going to name Search Participant once more.

To assault the participant, we’re going to use the montage animation I’ve ready which is the enemy’s assault animation:

Img 24

You possibly can copy the nodes from right here:

The Play Montage perform takes a number of parameters that we have to present. The primary one is the Mesh which represents the Skeletal Mesh Element on which the animation might be performed.

For that, I supplied the Mesh part from the BP_Enemy:

Img 25

For the Montage To Participant click on on the drop down record and choose the Mutant_Attack_Montage:

Img 26

When the montage finishes taking part in, we take a look at if Participant Detected is true, if that’s the case we are going to make the enemy transfer in the direction of the participant by calling Search Participant and that can repeat this identical course of over once more.

Compile and save the modifications and let’s run the sport to check it out:

Attaching Collision Parts To Sockets

Now that we’re attacking the participant, allow us to additionally deal harm. To do that, we have to edit the skeleton of the mutant mannequin. Within the Content material -> Enemy_Model folder open Mutant_Skeleton within the editor:

Img 27

Within the choices tab on the left aspect, find the RightHand within the skeleton hierarchy and Proper Click on ->Add Socket:

Img 28

This may create a socket on the precise arm of the mutant mannequin:
 

Img 29

Now we are able to open the BP_Enemy within the editor, and within the Parts tab, choose the Mesh part and from the Add Element button filter for Field Collision:
 

Img 30

Rename the Field to Injury Collision, and within the Particulars tab below the Sockets settings for the Father or mother Socket discipline click on on the little loop icon and seek for the RightHandSocket which is the identify of the socket we created within the Mutant_Skeleton a number of moments in the past:

Img 31

This may make the Injury Collision part a toddler of that socket, and we all know that socket is related to the precise hand of the mutant mannequin:
 

Img 32

Because of this the Injury Collision will transfer together with the precise hand of the mutant mannequin. We do must reposition and resize the Injury Collision part, so set the next values for the situation:

Img 33

And the next values for the Field Extent axis below the Form settings:

Img 34

Now the Injury Collision part seems like this:

Img 35

Animation Notification Occasions

The explanation why we went by means of all of this Field collision and socket arrange is as a result of we’re going to use the assault montage animation to set off the harm performance.

If we open the Mutant_Attack_Montage which is positioned in Content material ->Enemy Mannequin folder, and preview the animation we are going to see that the mutant is attacking with its proper hand:

Since we connected the Injury Collision part to the precise hand socket, when the assault animation is performed and the mutant strikes his proper hand, the Injury Collision part will transfer together with it and we are able to use that to detect the collision with the participant actor and deal harm.

To try this we have to add animation notifiers that can notify us when the animation is at a sure body.

We are able to try this by dragging the animation preview slider on the desired body within the animation timeline:

Img 36

Or we are able to set the precise body we would like on the precise aspect of the Filter search bar within the animation timeline:

Img 37

Once we are carried out with that, on the Notifies timeline, Proper Click on -> Add Notify -> New Notify and identify the brand new notify Assault Began:

We created a brand new animation notify, or notification, on body 11, which suggests after we play the assault animation and when the animation reaches body 11, the Assault Began notify might be known as, and we might be notified within the code when that occurs.

We additionally must create one other notification that can inform us that the animation has ended. Go on body 30, and create a brand new notify and identify it Assault Ended.

After you end, you will note two animation notifications within the assault animation timeline:

Img 38

Earlier than we entry the notification occasions within the blueprint editor, we have to go contained in the BP_Enemy editor, and below variables create a brand new boolean variable and identify it Can Deal Injury:

Img 39

Now open the BP_Enemy_Animation blueprint positioned in Content material -> Enemy_Model folder. Within the Occasion Graph tab, Proper Click on and seek for assault began:

Img 40

In the identical method seek for the assault ended anim notify node. We have already got a reference to the BP_Enemy within the BP_Enemy_Animation blueprint, so we are able to use that variable to entry the Can Deal Injury bool to vary its worth when the assault has began and when the assault ends:

Img 41

You possibly can copy the nodes from right here:

Going again to BP_Enemy blueprint, choose the Injury Collision part and within the Particulars tab below Occasions, click on on the inexperienced + button for the On Element Start Overlap:

Img 42

Within the Occasion Graph tab, for the On Element Start Overlap of the Injury Collision part, add the next nodes:

Img 43

You possibly can copy the nodes from right here:

When the Injury Collision part detects the collision with the participant actor, we’re going to test if we are able to deal harm to the participant, if that’s true, we are going to deal harm, or in our case print one thing to the console hehehe 🙂

Compile and save the modifications we made and let’s run the sport to check it out:

Each time the enemy attacked the participant and the collision was detected, we noticed Participant Broken printed within the prime left nook of the sport window.

In fact, in your sport, you’d add logic the place the participant can have a well being worth and that well being worth might be decreased when the enemy assaults him, however that is the essential logic that goes behind that.

Enemy AI C++ Model

Now we’re going to try the C++ model of the enemy AI that we created. First, in Content material -> C++ Lessons -> Enemy_AI folder, Proper Click on -> New C++ Class. Ensure that the category inherits from the Character then click on Subsequent:

Img 44

Give the category a reputation MutantEnemy and click on Create Class:
 

Img 45

Open the MutantEnemy.h file, and on the backside of the category declaration add the next strains of code:
 

				
					public:

	bool PlayerDetected;
	bool CanAttackPlayer;

	UPROPERTY(BlueprintReadWrite)
		bool CanDealDamage;

	class AEnemy_AICharacter* PlayerREF;

	UPROPERTY(EditAnywhere)
		class USphereComponent* PlayerCollisionDetection;

	UPROPERTY(EditAnywhere)
		class USphereComponent* PlayerAttackCollisionDetection;

	UPROPERTY(EditAnywhere)
		class UBoxComponent* DamageCollision;
				
			

These are all of the variables that we might want to create the enemy AI logic. And should you check out the variable names you’ll discover that these are the identical variables as those we used within the BP_Enemy blueprint.

For the CanDealDamage bool variable we added BlueprintReadWrite because the parameter within the UPROPERTY as a result of we have to entry that variable within the BP_Enemy_Animation and with the assistance of animation notifiers set it to true or false relying on the state of the assault animation.

The AEnemy_AICharacter declared on line 9 is definitely the category used to create the ThirdPersonCharacter blueprint that you could find in Content material -> ThirdPersonCPP -> Blueprints, which is the participant actor we use within the sport.

I’m addressing this simply to keep away from confusion, if there’s any, as a result of the category identify has enemy AI in it, and I didn’t need to create a brand new class simply to provide it one other identify and nonetheless use it for a similar goal with the identical code.

One factor that you’ll discover on strains 9, 12, 15, and 18, is that we’re utilizing ahead declaration to declare the variables that we’d like. In case you are not aware of the idea of ahead declaration, you may examine it by clicking right here.

Now open the MutantEnemy.cpp file, and first on the prime, above the category declaration add the imports we have to use the variables we declared within the .h file:

				
					#embrace "Enemy_AICharacter.h"
#embrace "Parts/SphereComponent.h"
#embrace "Parts/BoxComponent.h"
				
			

Should you don’t know which incorporates to make use of for particular variables, you may check out my information on that subject by clicking right here.

Within the constructor of the mutant class we’re going to create these elements and fasten them to the basis part:

				
					AMutantEnemy::AMutantEnemy()
{
 	// Set this character to name Tick() each body.  You possibly can flip this off to enhance efficiency should you do not want it.
	PrimaryActorTick.bCanEverTick = true;

	PlayerCollisionDetection =
		CreateDefaultSubobject(TEXT("Participant Collision Detection"));

	PlayerCollisionDetection->SetupAttachment(RootComponent);

	PlayerAttackCollisionDetection =
		CreateDefaultSubobject(TEXT("Participant Assault Collision Detection"));

	PlayerAttackCollisionDetection->SetupAttachment(RootComponent);

	DamageCollision = CreateDefaultSubobject(TEXT("Injury Collision"));
	DamageCollision->SetupAttachment(GetMesh(), TEXT("RightHandSocket"));
}
				
			

The code above is straight ahead as we’re simply creating the elements from code, however one particular factor that I’ll point out is on line 17 the place we’re attaching the DamageCollision variable to the mesh, we additionally must specify the socket identify the place we need to connect the DamageCollision, identical as what we did contained in the BP_Enemy blueprint.

Now we are able to create a blueprint out of the mutant enemy class, so go contained in the Content material -> Blueprints, Proper Click on -> Blueprint Class and for the All Lessons, click on on the drop down record and filter for mutantenemy:

Img 46

Identify the brand new blueprint BP_Enemy_CPP and open it within the editor. First, choose the Mesh part within the Parts tab and within the Particulars tab for the Mesh settings choose the Mutant mannequin, and for the Animation settings choose the BP_Enemy_Animation_C blueprint:

Img 47

As quickly as you choose the Mutant mannequin for the Mesh part, you’ll discover how the Injury Collision part is connected to the precise hand of the Mutant enemy:

Img 48

We additionally must resize the Injury Collision identical method we did within the BP_Enemy blueprint:

Img 34

And we have to change the Location X worth as nicely:

Img 33

The final step is to resize the Radius for the Participant Collision Detection to 800:

Img 49

And set the Radius for the Participant Assault Collision Detection to 200:

Img 50

Small Fixes Earlier than We Code C++ AI Logic

Earlier than we proceed to code the AI habits with C++, we have to make some small modifications to the BP_Enemy_Animation blueprint.

As a result of now we’re utilizing BP_Enemy_CPP blueprint, we have to change the enemy reference variable to the kind of the blueprint we’re utilizing.

Open the BP_Enemy_Animation blueprint and within the My Blueprint tab create a brand new variable, identify it Enemy CPP REF and set the sort to BP_Enemy_CPP and selected Object Reference from the record:

Img 51

From the Blueprint Initialize Animation occasion, as a substitute of getting the reference to the Enemy REF variable, we’re going to get a reference to Enemy CPP REF variable:

Img 52

You possibly can copy the nodes from right here:

Now from the AnimGraph tab, open the Idle – Run State Machine after which open Idle – Run animation, and as a substitute of utilizing the Enemy REF variable, we’re going to use Enemy CPP REF variable to get the rate of the enemy actor for the aim of the idle / run animation:

Img 53

You possibly can copy the nodes from right here:

We needed to make these modifications in any other case after we begin utilizing BP_Enemy_CPP we might see all sort of errors as a result of we are attempting to get the reference to the BP_Enemy contained in the BP_Enemy_Animation blueprint.

We additionally want to vary the code within the animation notifiers to make use of the Enemy CPP REF as a substitute of Enemy REF:

Img 58

You possibly can copy the nodes from right here:
 

The final step is to delete the BP_Enemy actor from the World Outliner tab, and drag the BP_Enemy_CPP actor within the sport:
 

Img 54

Creating And Setting Up The AI Controller Class

To create the AI logic we’re going to use the AIController class. Contained in the Content material -> C++ Lessons -> Enemy_AI folder, Proper Click on -> New C++ Class. Click on on the Present All Lessons checkbox and filter for ai controller, choose it and press Subsequent:

Img 55

Within the subsequent window give the category a reputation MutantAIController and create the category. Earlier than write code within the new class we created, we have to specify that the BP_Enemy_CPP blueprint will use MutantAIController class.

Open BP_Enemy_CPP blueprint, choose the BP_Enemy_CPP(self) prime father or mother, and within the particulars tab below Pawn settings, for the AI Controller Class click on on the drop down record and choose the MutantAIController class:

Img 56

Since we’re going to use the AI Controller class to manage the AI actor, we additionally must specify within the blueprint of the AI actor which AI Controller class goes to manage him.

AI Patrol Logic With C++

Now open Visible Studio and first we have to specify within the Construct.cs file that we need to use the navigation system. Within the Answer Explorer find the Enemy_AI.Construct.cs file and open it:

Img 57

Within the PublicDependencyModuleNames add NavigationSystem on the finish:

				
					PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", 
			"InputCore", "HeadMountedDisplay", "NavigationSystem" });
				
			

That is necessary if you wish to use the navigation system lessons, if we don’t add this line and attempt to use the navigation system, the code is not going to compile and we are going to see errors within the Output tab.

Now open the MutantAIController.h file, and add the next strains of code:

				
					public:
    void BeginPlay() override;

personal:

    class UNavigationSystemV1* NavArea;

    FVector RandomLocation;

public:

    UFUNCTION()
        void RandomPatrol();
				
			

On line 6 we declared UNavigationSystemV1 which is a variable that we’ll use to get random navigationable factors within the degree.

Within the RandomLocation variable we are going to retailer the random navigationable level we get from the UNavigationSystemV1.
 

And the RandomPatrol perform goes to make the enemy actor randomly patrol the extent.

Now open the MutantAIController.cpp file, and on the prime, beneath the primary #embrace line, add the next line of code:

				
					#embrace "NavigationSystem.h"
				
			

We have to embrace the navigation system with a purpose to use its performance. Inside BeginPlay we’re going to get a reference to the navigation system:

				
					void AMutantAIController::BeginPlay()
{
    Tremendous::BeginPlay();

    NavArea = FNavigationSystem::GetCurrent(this);

    RandomPatrol();
}
				
			

An important word right here, if you end up overriding BeginPlay for the AIController, just remember to name:
 

				
					Tremendous::BeginPlay();
				
			

in any other case your AI won’t ever transfer and you can be caught making an attempt to determine what you probably did fallacious.
 
Within the RandomPatrol perform, we’re going to get a random reachable location from the NavArea variable and make the AI transfer to that location:
 

				
					void AMutantAIController::RandomPatrol()
{    
    if (NavArea)
    {
        NavArea->K2_GetRandomReachablePointInRadius(GetWorld(), GetPawn()->GetActorLocation(),
            RandomLocation, 15000.0f);

        MoveToLocation(RandomLocation);
    }
}
				
			

TheK2_GetRandomReachablePointInRadius perform takes the world as the primary parameter.
 

The second parameter is the origin location from which we’re going to seek for the reachable level, for that parameter we handed the situation of the actor that’s controller by the AI Controller which is our BP_Mutant_CPP.

The third parameter is the reference to the FVector variable that can maintain the random location values.
 
And the fourth parameter is the radius from the origin location during which we’re going to get the random location.
 
After we get the random location we merely name the MoveToLocation perform to make the AI transfer to the required location.
 
We’re carried out with the random patrol motion and we are able to take a look at this now, however this may make the AI patrol solely as soon as, as a result of when the motion finishes of the AI finishes, we aren’t calling RandomPatrol to make the AI transfer once more.
 
To do that, we have to subscribe to the OnRequestFinished occasion of the PathFollowingComponent and we’re going to try this within the MutantEnemy class.
 
However earlier than we try this, I’m going to go away the completed model of the MutantAIController.h and .cpp file as a reference:
 

				
					#pragma as soon as

#embrace "CoreMinimal.h"
#embrace "AIController.h"
#embrace "MutantAIController.generated.h"

/**
 * 
 */
UCLASS()
class ENEMY_AI_API AMutantAIController : public AAIController
{
	GENERATED_BODY()
	
public:
    void BeginPlay() override;

personal:

    class UNavigationSystemV1* NavArea;

    FVector RandomLocation;

public:

    UFUNCTION()
        void RandomPatrol();

};
				
			

MutantAIController.cpp:
 

				
					#embrace "MutantAIController.h"

#embrace "NavigationSystem.h"


void AMutantAIController::BeginPlay()
{
    Tremendous::BeginPlay();

    NavArea = FNavigationSystem::GetCurrent(this);

    RandomPatrol();
}

void AMutantAIController::RandomPatrol()
{    
    if (NavArea)
    {
        NavArea->K2_GetRandomReachablePointInRadius(GetWorld(), GetPawn()->GetActorLocation(),
            RandomLocation, 15000.0f);

        MoveToLocation(RandomLocation);
    }
}
				
			

Now open the MutantEnemy.h file and proper beneath the place we declared the DamageCollision variable, add the next strains of code:

				
					class AMutantAIController* MutantAIController;

	void OnAIMoveCompleted(struct FAIRequestID RequestID, const struct FPathFollowingResult& Consequence);
				
			

Since we specified that the MutantAIController is the controller of the MutantEnemy, we have to get a reference to it with a purpose to carry out AI actions, therefore the MutantAIController variable declaration.

The OnAIMoveCompleted perform will subscribe to the OnRequestFinished occasion to tell us when the AI motion has completed.

Now open the MutantEnemy.cpp file and beneath the final #embrace, add the next strains:

				
					#embrace "MutantAIController.h"
#embrace "Navigation/PathFollowingComponent.h"
#embrace "AITypes.h"
				
			

We’d like the consists of with a purpose to use capabilities from the AIController and to have the ability to use FAIRequestID and FPathFollowingResult as parameters within the OnAIMoveCompleted perform.

In BeingPlay, we’re going to get a reference to the AIController and subscribe to the OnRequestFinished occasion:

				
					void AMutantEnemy::BeginPlay()
{
	Tremendous::BeginPlay();

	MutantAIController = Forged(GetController());
	MutantAIController->GetPathFollowingComponent()->OnRequestFinished.AddUObject
	(this, &AMutantEnemy::OnAIMoveCompleted);
}
				
			

And contained in the OnAIMoveCompleted perform, we’re going to name the MutantAIController to make the AI patrol once more:

				
					void AMutantEnemy::OnAIMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult& Consequence)
{
	MutantAIController->RandomPatrol();
}
				
			

Save and compile the code and let’s run the sport to check it out:
 

As you may see, the enemy is patrolling the extent cleverly avoiding all obstacles in its method. You possibly can change the radius parameter worth within the K2_GetRandomReachablePointInRadius perform to make the AI patrol farther from its location.

Detecting And Chasing The Participant

To make the AI chase the participant we have to detect the participant’s presence close to the enemy. For that we have to create capabilities that we’ll bind to on part being and finish overlap of the collision elements.

Within the MutantEnemy.h file beneath the road the place we declared the OnAIMoveCompleted perform, add the next strains of code:

				
					UPROPERTY(EditAnywhere)
		float StoppingDistance = 100.0f;

	FTimerHandle SeekPlayerTimerHandle;

	UFUNCTION()
		void MoveToPlayer();

	UFUNCTION()
		void SeekPlayer();

	UFUNCTION()
		void StopSeekingPlayer();

	UFUNCTION()
		void OnPlayerDetectedOverlapBegin(class UPrimitiveComponent* OverlappedComp, 
			class AActor* OtherActor, class UPrimitiveComponent* OtherComp, 
			int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION()
		void OnPlayerDetectedOverlapEnd(class UPrimitiveComponent* OverlappedComp,
			class AActor* OtherActor, class UPrimitiveComponent* OtherComp, 
			int32 OtherBodyIndex);

	UFUNCTION()
		void OnPlayerAttackOverlapBegin(class UPrimitiveComponent* OverlappedComp,
			class AActor* OtherActor, class UPrimitiveComponent* OtherComp,
			int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
	
	UFUNCTION()
		void OnPlayerAttackOverlapEnd(class UPrimitiveComponent* OverlappedComp,
			class AActor* OtherActor, class UPrimitiveComponent* OtherComp,
			int32 OtherBodyIndex);

	UFUNCTION()
		void OnDealDamageOverlapBegin(class UPrimitiveComponent* OverlappedComp,
			class AActor* OtherActor, class UPrimitiveComponent* OtherComp,
			int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
				
			

The StoppingDistance variable goes to find out the stopping distance between the enemy and the participant.

I’ve added the EditAnywhere parameter within the UPROPERTY which implies that we will edit this variable on the blueprint occasion, so you may selected to make the enemy cease at the next or decrease distance from the participant actor.

As for the SeekPlayerTimerHandler variable, we’re going to use it to create a timer that can name the SeekPlayer perform in a loop, the identical method we did within the BP_Enemy blueprint, and we’re additionally going to make use of that variable to cease the timer.

As for the capabilities that I’ve declared I gave them the identical names as those we created in BP_Enemy blueprint, and you’ll already assume that these capabilities will carry out the identical actions as those in BP_Enemy.

First we’re going to bind the capabilities to on part start and overlap occasions of our collision elements. Open MutantEnemy.cpp file and in BeginPlay beneath the road the place we bind the OnAIMoveCompleted add the next strains of code:

				
					PlayerCollisionDetection->OnComponentBeginOverlap.AddDynamic(this, 
		&AMutantEnemy::OnPlayerDetectedOverlapBegin);

	PlayerCollisionDetection->OnComponentEndOverlap.AddDynamic(this,
		&AMutantEnemy::OnPlayerDetectedOverlapEnd);

	PlayerAttackCollisionDetection->OnComponentBeginOverlap.AddDynamic(this,
		&AMutantEnemy::OnPlayerAttackOverlapBegin);

	PlayerAttackCollisionDetection->OnComponentEndOverlap.AddDynamic(this,
		&AMutantEnemy::OnPlayerAttackOverlapEnd);

	DamageCollision->OnComponentBeginOverlap.AddDynamic(this,
		&AMutantEnemy::OnDealDamageOverlapBegin);
				
			

Now we’re going to create and code the capabilities one after the other beginning with MoveToPlayer perform. Under the OnAIMoveCompleted perform, add the next strains of code:

				
					void AMutantEnemy::MoveToPlayer()
{
	MutantAIController->MoveToLocation(PlayerREF->GetActorLocation(), StoppingDistance, true);
}
				
			

Within the MoveToPlayer perform we’re merely calling the MutantAIController’s MoveToLocation perform, passing it the situation of the PlayerREF variable which is a reference to the participant actor within the sport.
 
The second parameter is the stopping distance between the enemy and the goal location e.g. participant’s location.
 
And the third parameter signifies whether or not the MoveToLocation perform will use path discovering to keep away from all potential obstacles that can get within the AI’s method.
 
Subsequent, beneath the MoveToPlayer perform create the SeekPlayer perform:
 

				
					void AMutantEnemy::SeekPlayer()
{
	MoveToPlayer();
	GetWorld()->GetTimerManager().SetTimer(SeekPlayerTimerHandle, this,
		&AMutantEnemy::SeekPlayer, 0.25f, true);
}
				
			

Contained in the SeekPlayer we’re first calling the MoveToPlayer perform to make the AI transfer to participant, after which we’re making a timer that can name the SeekPlayer perform each 0.25 seconds.
 
The primary parameter within the SetTimer perform is the SeekPlayerTimerHandler, and the reference to this timer might be saved in that variable, which implies that with a purpose to cease the timer, we merely want to make use of the SeekPlayerTimerHandler variable:
 

				
					void AMutantEnemy::StopSeekingPlayer()
{
	GetWorld()->GetTimerManager().ClearTimer(SeekPlayerTimerHandle);
}
				
			

By calling the ClearTimer perform of the TimerManager and passing it SeekPlayerTimerHandler we are going to cease the timer and it’ll not proceed to name the SeekPlayer perform anymore.
 
Once we detect the participant’s presence we’re going to set the PlayerDetected worth to true and name the SeekPlayer perform to make the AI chase the participant:
 

				
					void AMutantEnemy::OnPlayerDetectedOverlapBegin(UPrimitiveComponent* OverlappedComp,
	AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, 
	bool bFromSweep, const FHitResult& SweepResult)
{
	PlayerREF = Forged(OtherActor);
	if (PlayerREF)
	{
		PlayerDetected = true;
		SeekPlayer();
	}
}
				
			

And when the participant goes outdoors the bounds of the participant detection collision part, we’re going to set the PlayerDetected worth to false, then we’re going to name StopSeekingPlayer in order that the AI will cease chasing the participant, and lastly we are going to make the AI patrol once more:
 

				
					void AMutantEnemy::OnPlayerDetectedOverlapEnd(UPrimitiveComponent* OverlappedComp, 
	AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	PlayerREF = Forged(OtherActor);
	if (PlayerREF)
	{
		PlayerDetected = false;
		StopSeekingPlayer();
		MutantAIController->RandomPatrol();
	}
}
				
			

When the enemy comes near the participant actor and the participant collides with the participant assault collision detection part we are going to set the CanAttackPlayer worth to true:
 

				
					void AMutantEnemy::OnPlayerAttackOverlapBegin(UPrimitiveComponent* OverlappedComp, 
	AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, 
	bool bFromSweep, const FHitResult& SweepResult)
{
	PlayerREF = Forged(OtherActor);
	if (PlayerREF)
	{
		CanAttackPlayer = true;
	}
}
				
			

And when the participant runs away from the enemy and exits the can assault participant collision part we are going to set the CanAttackPlayer worth to false, and we are going to make the AI chase the participant as a result of regardless that the participant actor did exit the can assault participant collision part he’s nonetheless contained in the participant detected collision part:
 

Img 59

				
					void AMutantEnemy::OnPlayerAttackOverlapEnd(UPrimitiveComponent* OverlappedComp, 
	AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	PlayerREF = Forged(OtherActor);
	if (PlayerREF)
	{
		CanAttackPlayer = false;

		SeekPlayer();
	}
}
				
			

And lastly, after we assault the participant, we are going to detect if we are able to deal harm, after which we are going to deal harm to the participant:
 

				
					void AMutantEnemy::OnDealDamageOverlapBegin(UPrimitiveComponent* OverlappedComp,
	AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, 
	bool bFromSweep, const FHitResult& SweepResult)
{
	PlayerREF = Forged(OtherActor);
	if (PlayerREF && CanDealDamage)
	{
		// deal harm to participant
		UE_LOG(LogTemp, Warning, TEXT("Participant Broken"));
	}
}
				
			

For our instance we’re simply going to print to the Output Log tab, however on your personal video games you’ll create variables that can symbolize the participant’s well being and you’ll subtract from that worth when the enemy assaults the participant.
 
Earlier than we are able to take a look at this, we have to make some modifications within the OnAIMoveCompleted perform:
 

				
					void AMutantEnemy::OnAIMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult& Consequence)
{
	if (!PlayerDetected)
	{
		MutantAIController->RandomPatrol();
	}
	else if (PlayerDetected && CanAttackPlayer)
	{
		StopSeekingPlayer();

		// assault participant
		UE_LOG(LogTemp, Warning, TEXT("Participant ATTACKED"));
	}
}
				
			

As a substitute of constructing the AI patrol once more when OnAIMoveCompleted is named, we are going to first take a look at if the participant just isn’t detected on line 3, if that’s not true then we are going to make the AI patrol once more. But when the participant is detected and we are able to assault the participant, we are going to first cease in search of the participant, after which we are going to assault him.
 
At present for the assault I’m going to print to the Output Log tab, however after we take a look at this a part of the tutorial we are going to play the assault animation and make the enemy assault the participant.
 
 Save and compile the code and let’s run the sport to check it out:
 

As quickly because the enemy detects the participant it begins transferring in the direction of him, and when it reaches the participant, of CanAttackPlayer is true, we noticed that Participant ATTACKED was printed within the console.

Attacking The Participant And Dealing Injury

To make the enemy assault the participant we have to play the enemy assault montage animation. To do that, we’d like a number of variables.

Within the MutantEnemy.h file, on the backside of the category add the next strains of code:

				
					UPROPERTY(EditAnywhere)
		class UAnimMontage* EnemyAttackAnimation;

	class UAnimInstance* AnimInstance;

	UFUNCTION(BlueprintCallable)
		void AttackAnimationEnded();
				
			

EnemyAttackAnimation is a reference to the enemy assault montage. AnimInstance is a reference to the anim occasion that can play the assault animation.

And the AttackAnimationEnded perform goes to behave like a delegate that can inform us when the animation has ended. Discover how I added BlueprintCallable within the UFUNCTION parameter, it is because we’re going to create one other notify occasion within the enemy assault montage, and we’re going to name AttackAnimationEnded from that occasion.

Earlier than we proceed just remember to declare the AttackAnimationEnded perform within the MutantEnemy.cpp file, you may click on right here to see a shortcut methods to declare perform.

Now save and compile the category and open BP_Enemy_CPP blueprint within the editor.

Within the Parts tab, choose the BP_Enemy_CPP(self) prime father or mother, and within the Particulars tab for the Enemy Assault Animation, click on on the drop down record and choose Mutant_Attack_Montage:

Img 60

Compile and save the modifications made to the blueprint after which open the Mutant_Attack_Montage animation within the editor.

Close to the top of the assault animation below the Notifies timeline, Proper Click on -> Add Notify -> New Notify and provides the brand new notify identify Assault Animation Ended:

Img 61

Save the brand new change and open the BP_Enemy_Animation blueprint within the editor. Within the Occasion Graph Proper Click on and within the search bar filter for assault animation ended notify:

Img 62

From the Assault Animation Ended notify name the Assault Animation Ended perform that we declared within the MutantEnemy class:
 

Img 63

You possibly can copy the nodes from right here:
 

Compile and save the brand new modifications and open MutantEnemy.cpp file. First we’re going to add the extra consists of that we have to play the assault animation. So beneath the final embrace add the next strains:

				
					#embrace "Animation/AnimInstance.h"
#embrace "Animation/AnimMontage.h"
				
			

On the backside of BeginPlay perform get a reference to the anim occasion:

				
					AnimInstance = GetMesh()->GetAnimInstance();
				
			

In OnAIMoveCompleted, make modifications in order that the enemy assaults the participant when it reaches his place and the CanAttackPlayer worth is about to true:

				
					void AMutantEnemy::OnAIMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult& Consequence)
{
	if (!PlayerDetected)
	{
		MutantAIController->RandomPatrol();
	}
	else if (PlayerDetected && CanAttackPlayer)
	{
		StopSeekingPlayer();

		// assault participant
		AnimInstance->Montage_Play(EnemyAttackAnimation);
	}
}
				
			

If the enemy tries to assault the participant e.g. the assault animation begins taking part in, and the participant runs away from the enemy at that second, we’re going to cease the assault animation and begin chasing the participant once more.

For that, we have to make some modifications within the OnPlayerAttackOverlapEnd perform:

				
					void AMutantEnemy::OnPlayerAttackOverlapEnd(UPrimitiveComponent* OverlappedComp, 
	AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	PlayerREF = Forged(OtherActor);
	if (PlayerREF)
	{
		CanAttackPlayer = false;

		// cease the assault animation and chase the participant
		AnimInstance->Montage_Stop(0.0f, EnemyAttackAnimation);
		
		SeekPlayer();
	}
}
				
			

Calling Montage_Stop perform from AnimInstance and passing 0.0f as the primary parameter will instantly cease taking part in the supplied animation which is the second parameter for that perform and in our case the EnemyAttackAnimation.

And the final step is to assault the participant once more when the animation ends, which we are going to do within the AttackAnimationEnded perform:

				
					void AMutantEnemy::AttackAnimationEnded()
{
	if (CanAttackPlayer)
	{
		AnimInstance->Montage_Play(EnemyAttackAnimation);
	}
}
				
			

Earlier than we take a look at this out, I’m going to go away the completed variations of MutantEnemy.h and .cpp recordsdata as a reference:
 

				
					#embrace "CoreMinimal.h"
#embrace "GameFramework/Character.h"
#embrace "MutantEnemy.generated.h"

UCLASS()
class ENEMY_AI_API AMutantEnemy : public ACharacter
{
	GENERATED_BODY()

public:
	// Units default values for this character's properties
	AMutantEnemy();

protected:
	// Known as when the sport begins or when spawned
	digital void BeginPlay() override;

public:	
	// Known as each body
	digital void Tick(float DeltaTime) override;

	// Known as to bind performance to enter
	digital void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

public:

	bool PlayerDetected;
	bool CanAttackPlayer;

	UPROPERTY(BlueprintReadWrite)
		bool CanDealDamage;

	class AEnemy_AICharacter* PlayerREF;

	UPROPERTY(EditAnywhere)
		class USphereComponent* PlayerCollisionDetection;

	UPROPERTY(EditAnywhere)
		class USphereComponent* PlayerAttackCollisionDetection;

	UPROPERTY(EditAnywhere)
		class UBoxComponent* DamageCollision;

	class AMutantAIController* MutantAIController;

	void OnAIMoveCompleted(struct FAIRequestID RequestID, const struct FPathFollowingResult& Consequence);
	
	UPROPERTY(EditAnywhere)
		float StoppingDistance = 100.0f;

	FTimerHandle SeekPlayerTimerHandle;

	UFUNCTION()
		void MoveToPlayer();

	UFUNCTION()
		void SeekPlayer();

	UFUNCTION()
		void StopSeekingPlayer();

	UFUNCTION()
		void OnPlayerDetectedOverlapBegin(class UPrimitiveComponent* OverlappedComp, 
			class AActor* OtherActor, class UPrimitiveComponent* OtherComp, 
			int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION()
		void OnPlayerDetectedOverlapEnd(class UPrimitiveComponent* OverlappedComp,
			class AActor* OtherActor, class UPrimitiveComponent* OtherComp, 
			int32 OtherBodyIndex);

	UFUNCTION()
		void OnPlayerAttackOverlapBegin(class UPrimitiveComponent* OverlappedComp,
			class AActor* OtherActor, class UPrimitiveComponent* OtherComp,
			int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
	
	UFUNCTION()
		void OnPlayerAttackOverlapEnd(class UPrimitiveComponent* OverlappedComp,
			class AActor* OtherActor, class UPrimitiveComponent* OtherComp,
			int32 OtherBodyIndex);

	UFUNCTION()
		void OnDealDamageOverlapBegin(class UPrimitiveComponent* OverlappedComp,
			class AActor* OtherActor, class UPrimitiveComponent* OtherComp,
			int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UPROPERTY(EditAnywhere)
		class UAnimMontage* EnemyAttackAnimation;

	class UAnimInstance* AnimInstance;

	UFUNCTION(BlueprintCallable)
		void AttackAnimationEnded();

};
				
			

MutantEnemy.cpp:
 

				
					#embrace "MutantEnemy.h"
#embrace "Enemy_AICharacter.h"
#embrace "Parts/SphereComponent.h"
#embrace "Parts/BoxComponent.h"
#embrace "MutantAIController.h"
#embrace "Navigation/PathFollowingComponent.h"
#embrace "AITypes.h"
#embrace "Animation/AnimInstance.h"
#embrace "Animation/AnimMontage.h"


// Units default values
AMutantEnemy::AMutantEnemy()
{
 	// Set this character to name Tick() each body.  You possibly can flip this off to enhance efficiency should you do not want it.
	PrimaryActorTick.bCanEverTick = true;

	PlayerCollisionDetection =
		CreateDefaultSubobject(TEXT("Participant Collision Detection"));

	PlayerCollisionDetection->SetupAttachment(RootComponent);

	PlayerAttackCollisionDetection =
		CreateDefaultSubobject(TEXT("Participant Assault Collision Detection"));

	PlayerAttackCollisionDetection->SetupAttachment(RootComponent);

	DamageCollision = CreateDefaultSubobject(TEXT("Injury Collision"));
	DamageCollision->SetupAttachment(GetMesh(), TEXT("RightHandSocket"));

}

// Known as when the sport begins or when spawned
void AMutantEnemy::BeginPlay()
{
	Tremendous::BeginPlay();

	MutantAIController = Forged(GetController());
	MutantAIController->GetPathFollowingComponent()->OnRequestFinished.AddUObject
	(this, &AMutantEnemy::OnAIMoveCompleted);

	PlayerCollisionDetection->OnComponentBeginOverlap.AddDynamic(this, 
		&AMutantEnemy::OnPlayerDetectedOverlapBegin);

	PlayerCollisionDetection->OnComponentEndOverlap.AddDynamic(this,
		&AMutantEnemy::OnPlayerDetectedOverlapEnd);

	PlayerAttackCollisionDetection->OnComponentBeginOverlap.AddDynamic(this,
		&AMutantEnemy::OnPlayerAttackOverlapBegin);

	PlayerAttackCollisionDetection->OnComponentEndOverlap.AddDynamic(this,
		&AMutantEnemy::OnPlayerAttackOverlapEnd);

	DamageCollision->OnComponentBeginOverlap.AddDynamic(this,
		&AMutantEnemy::OnDealDamageOverlapBegin);

	AnimInstance = GetMesh()->GetAnimInstance();
}

// Known as each body
void AMutantEnemy::Tick(float DeltaTime)
{
	Tremendous::Tick(DeltaTime);

}

// Known as to bind performance to enter
void AMutantEnemy::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Tremendous::SetupPlayerInputComponent(PlayerInputComponent);

}

void AMutantEnemy::OnAIMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult& Consequence)
{
	if (!PlayerDetected)
	{
		MutantAIController->RandomPatrol();
	}
	else if (PlayerDetected && CanAttackPlayer)
	{
		StopSeekingPlayer();

		// assault participant
		AnimInstance->Montage_Play(EnemyAttackAnimation);
	}
}

void AMutantEnemy::MoveToPlayer()
{
	MutantAIController->MoveToLocation(PlayerREF->GetActorLocation(), StoppingDistance, true);
}

void AMutantEnemy::SeekPlayer()
{
	MoveToPlayer();
	GetWorld()->GetTimerManager().SetTimer(SeekPlayerTimerHandle, this,
		&AMutantEnemy::SeekPlayer, 0.25f, true);
}

void AMutantEnemy::StopSeekingPlayer()
{
	GetWorld()->GetTimerManager().ClearTimer(SeekPlayerTimerHandle);
}

void AMutantEnemy::OnPlayerDetectedOverlapBegin(UPrimitiveComponent* OverlappedComp,
	AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, 
	bool bFromSweep, const FHitResult& SweepResult)
{
	PlayerREF = Forged(OtherActor);
	if (PlayerREF)
	{
		PlayerDetected = true;
		SeekPlayer();
	}
}

void AMutantEnemy::OnPlayerDetectedOverlapEnd(UPrimitiveComponent* OverlappedComp, 
	AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	PlayerREF = Forged(OtherActor);
	if (PlayerREF)
	{
		PlayerDetected = false;
		StopSeekingPlayer();
		MutantAIController->RandomPatrol();
	}
}

void AMutantEnemy::OnPlayerAttackOverlapBegin(UPrimitiveComponent* OverlappedComp, 
	AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, 
	bool bFromSweep, const FHitResult& SweepResult)
{
	PlayerREF = Forged(OtherActor);
	if (PlayerREF)
	{
		CanAttackPlayer = true;
	}
}

void AMutantEnemy::OnPlayerAttackOverlapEnd(UPrimitiveComponent* OverlappedComp, 
	AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	PlayerREF = Forged(OtherActor);
	if (PlayerREF)
	{
		CanAttackPlayer = false;

		// cease the assault animation and chase the participant
		AnimInstance->Montage_Stop(0.0f, EnemyAttackAnimation);
		
		SeekPlayer();
	}
}

void AMutantEnemy::OnDealDamageOverlapBegin(UPrimitiveComponent* OverlappedComp,
	AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, 
	bool bFromSweep, const FHitResult& SweepResult)
{
	PlayerREF = Forged(OtherActor);
	if (PlayerREF && CanDealDamage)
	{
		// deal harm to participant
		UE_LOG(LogTemp, Warning, TEXT("Participant Broken"));
	}
}

void AMutantEnemy::AttackAnimationEnded()
{
	if (CanAttackPlayer)
	{
		AnimInstance->Montage_Play(EnemyAttackAnimation);
	}
}
				
			

Just be sure you save and compile the code. Now let’s run the sport to check it out:
 

If by any probability you see Participant Injury printed a number of instances within the Output Log if you assault, you may transfer the Assault Ended notify a little bit nearer to the Assault Began notify within the Mutant_Attack_Montage animation:

Img 64

The place To Go From Right here

On this tutorial we noticed easy and intermediate methods how we are able to arrange enemy AI in Unreal Engine utilizing Blueprints and C++.

If you wish to study a extra superior method methods to arrange enemy AI utilizing Conduct Timber which provides you extra management and helps you create lifelike enemies, you are able to do that in my Enemy AI With Conduct Timber In Unreal Engine tutorial.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments