Game in-depth section Navigation system
Hello, this is Younghoon Lee
What we're going to learn today is the Navigation System
In this section, the path finding system of Unreal
the Navigation System, is what we will learn about
And using a Navigation Invoker
we're going to create paths in real-time
and learn about ways to travel towards the destination
Also, using this, we'll learn how to
implement the patrol function
Path finding using the Navigation System
This time, we're going to try processing the Path Finding
Normally, the enemy comes toward the player like this
But what would happen if there's an obstacle in-between?
Let's place a cube and see the results
Make an obstacle like this and execute
Then the enemy can't come towards the player
That's because the enemy is going straight forward
To go towards the direction of the player
The direction is set like this
Through AddMovementInput
it continues to go in that direction
But in that direction, if there's an obstacle
then it can't move properly
So in engines like Unreal
to process these
they provide a Path Finding System
Usually, in English
they call it Path Finding
They call it like this
In other words, it's called Navigation
Like this
Then using the Navigation System of Unreal
we're going to produce this
Normally, for Navigation and Path Finding
there's the most famous algorithm
There's something called A* algorithm among the algorithms
Basically, when there's a surface like this
it's the concept of the finding the shortest path
For example, like this
if they're arranged like this
For example, you want to move quickly from here to here
Then let's say that there's an obstacle here
Then for example, let's say that there are obstacles like this
Then normally, going this way is the fastest
but you would end up traveling like this
The most complicated it gets
the more calculation it performs
Basically, this A* algorithm is used
for Path Finding
Actually, A* algorithm not only can do
these rectangular forms
but it can also do triangles
It can use triangles that look like these
Or pentagons, hexagons, or octagons
These can also be used
So the side adjacent to the current side
Finding the shortest path toward that side
is what this formula does
It's implemented like this in Unreal as well
Then to process these, basically
certain data has to be made
So to put this in more simple terms
we need to make paths
We can travel only if there are paths
Then in Unreal, to carry out this Path Finding
we need two main elements
One of them is path
We need paths, that's how we can travel
Second, we need the subject that actually travels there
The controller that finds the path
In a way, Path Finding is A.I.
We can call it A.I.
It's basically an A.I.
The thing that process, that corresponds to the A.I. is
the controller that finds the path
Here, it's called AIController
That's how we can call it
So first, we need to make the path and the controller
Basically, to make the path
if you look here, in Place Actors
there's a part called Volumes
Go to Volumes
and there's something called Nav Mesh Bounds Volume
Take this out
This is the volume that creates the path
It can create an area
We'll try using this
Then if you look at the Volume
you can set its size
First, place it in the center
Now we can widen the size
If you look here, there's Brush Settings
You can use this
Or you can use Scale
You can adjust either of them
I'll use Brush Settings
Select this
Adequately.. should we put it at 2000?
Then it's about this much
Then I think it should be bigger
Let's see... about 4 times bigger? Should we put it at 8000?
Then it's about this much. And for Y as well, 8000
Then it fills up entirely
We don't need to adjust Z necessarily
At this point, in order to see where the actual path is, to see the volume
Without pressing anything
Select the Viewport
And press the P key on the keyboard
Press P, and the area appears like this
This now becomes the path
Then since this is the path, on top of this path
The A.I., the enemy, on top of this path
should be made to travel around the obstacle, this way
Should we arrange the obstacle to be a little longer?
I'll widen it a little
Arrange it like this, and we're going to make it find the path
This time, let's take a look at the enemy
Select the enemy, and in its details
Go all the way down, and there's a part called Pawn
If you look at the Pawn
it's set like this, right?
In AI Controller Class, AIController
is selected, right?
Auto Possess AI is set as Placed in World
If it's set like this, what happens is
Normally, the controller of this guy is AIController
Everyone, Unreal is basically this kind of concept
The game board, or the world is there
And there are characters on this world
Pawns or characters
Then the user, out of the pawns here
decides which one to get hold of and move
That's what they're controlling
So normally, there's the Player Controller
and then
This one receives input, and with the input value
there's the concept of being able to control it
Other than this, Path Finding
has a separate AIController
So for AI too, it gets hold of this guy
It's the concept of possessing
The player is possessing this
And this is possessed by the AI
That's the concept you should understand it as
Then basically, this guy is set up like this. And also
What this Auto Possess AI is, is if you expand this part
There are two types. Spawned and Placed in World
It can do both of them
What this means, is that when this character is arranged on level
we can place it static
We can arrange like this through drag and drop
But instead of that, Spawn Actor can be used
to arrange this on level
Which means we can spawn it
Then when we spawn it, this controller
needs to be decided on how to possess it
So when you look here, it looks like this
If it's like this, for example, and then
let's say that you made a creator that creates the enemy
Then that guy doesn't get possessed by the AIController
That's because only for the ones placed in world
the controller automatically
possess them, that's the concept
So this has to be changed like this
Later, if you set the enemy to be created
then when the enemy is spawned, the AI Controller automatically
possesses the enemy from the start
That's how you should configure it
But we're not going to make the enemy creator
We're only going to deal with one, so actually this one
doesn't really make a difference, but as you work more
you may experience trouble due to this
That's why I touched upon it
You should normally set it to this setting
Save it
Then we're going to move the enemy
We'll have to process that in Move
But I told you that there are two conditions
One is path. The path is already created with Volume
Second one needs to be proceeded using the AIController
So if you look in EnemyFSM
we don't have an AIController
So here, in order to have an AIController
we'll make a variable
It's called UPROPERTY
class AAIController
Controllers begin with A
They're in the form of actors
Same thing with player controllers, they start with A
Then, we'll put AI
Then we should fill in this value
We'll fill it in BeginPlay
Here, AI will be in Me because Me possesses it
In Me, do GetController, and you'll be able to bring it
We'll have to cast it to use it
Put Cast
Here, it will be AAIController
Then since we now brought it
we'll take this and move it
Go to TickMove, and we're going to move it using AI
Here, put Me, and AddMovementInput as comment
Then we'll move with the AI
In AI, type Move
and there's MoveTo or MoveToActor, Location, etc
These are here for you to use
From here, I'll use MoveToLocation
This function makes you insert the destination
And it's like this
Since it's difficult to view
we'll take a quick look in the blueprint
Here, put AI MoveTo
and these pop up
If you look here, if you put location into the destination
or put the Target Actor that corresponds to that destination
it can move to that area
And for this Acceptance Radius
it's a range value that indicates, if you reached near that area
then you've arrived
So for example
exactly in that position, that location
needs to be matched in order to arrive
But that's difficult to calculate exactly
That's why we give it a range
Right now, it's set as 5 cm, but that's a little difficult
So you can set this to like 50 cm or something
This, you guys, according to the concept
you can input an appropriate value
So when you arrive, from here
these kinds of signals appear
So similar to this, you need to fill in values here
If you look here, there's Dest., or the Destination
There's the destination, and same thing here
there's the AcceptanceRadius
And similarly, StopOnOverlap
Right? So that's how it's like
Here, what you need to fill in is
The most important part is this, Destination
The Destination is actually the Target's GetActorLocation
That's the Destination
So we'll keep it for now as FVector
We'll set it as destination and keep it
Then change the direction like this
And then we'll insert the destination into here
And to make it arrive at the approximate location
we can put, for example, like 50
But in order to use this
you can't use it as is
You have to add a module
So from here, go to the Build.cs file
Remember? Where you add the module
We're going to add it here
We're going to add two
But it will be good to take a look at this too
Then since it's AI Controller
Should we search it up?
If you look at AIController
You need to use AIModule for it
So this module
will be added here like this
It's AIModule
And while we're on it, we'll add another one
Here, there's AIModule
but when we do Path Finding
there's something called UNavigationSystemV1
We're going to use this class
We'll add the module beforehand as well
If you look here, the module here is NavigationSystem
We'll write this as-is on here
So AIModule and NavigationSystem
are the two modules that we'll add
And we'll come back to here
Here, we're going to use this
We'll have to add headers
For header, like this
Add a header called AIController
If you look here, you need to add it like this
Like this
Add it like this
And since we made it here, let's try executing
If it actually goes
Close Unreal for now
We'll delete this because we don't need it
Close it for now
We'll try building it here
Execute it again
Then the enemy diverts from the obstacle
and comes toward the player like this
If I run away, it follows well like this
This is the basic
Path Finding System that's provided
So the core point is to create the path
and move by using the AIController
It's finding the path
Path Finding is ultimately heading towards the destination
That's the concept of destination that you should put in
Path Finding and the Patrol Function using the Navigation Invoker
Then using this function, we do Path Finding
We're going to make this kind of concept
If you take a look, there's the overall path like this
And there's the enemy standing here
But the player is here
So there's the distance at which the enemy can sense the player
And if it can't sense anything
then it marks a temporary point
and travels to that area
Here, it searches again and goes to another area
While it moves about randomly
if, within the sensing area of the enemy
the player comes in like this
The player comes in like this
Like this
Then instead of going to the place it was headed
the enemy comes toward the player
And if the player runs away again
it runs away to a far area
If it goes beyond a certain distance
the enemy continues to patrol in its original area
So the concept of patrolling
and the concept of tracking, is what we want to make
There are various ways to make these
We can make a state
Patrol or track during the moving state
We can process it like that
There are various ways
In Unreal, ways to process path
exist in many kinds, and among them, there's something called Invoker
Invoker is this kind of concept
Path is something made in a static way
at first. What it means is that
Let's say that there's a big path
We made a very big map
and we made the path information there
Then creating the path information at first
will take a long time
So when it's all made, then on top of the path
the AI is there, and it moves about
That's the concept. But if it's an open world
it will be a problem
Because this map will be huge
Then every time the level of the open world is adjusted
the path has to be re-created
In order to carry out those things
there may be lags
or functional issues may arise
So there's this concept
What this Invoker is, is that
For the overall path
there may be the static concept
and there's also the dynamic concept
Static means everything is already set
They're made ahead of time
That's what it means
Dynamic means that it's made in real-time
Right?
So if Invoker is used like this
the path can be made and processed in real-time
Then what happens when the path is made in Invoker, is that
there's the new area that it will search
Then it will move like this
Then there's the existing path like this, right?
Then it will make a brand new path
Then the existing path is out of the boundary
Then it will delete this
So it dynamically continues making
The concept is to recognize the area around them as paths
So if it's far away, it's not on top of the path
It recognizes it as outside of its recognition range
So it's not a path
Using this, patrolling and tracking can be done
It can carry this out by measuring the distance as well
but we use Invokers like this
We call it the NavigationInvoker
We can use this to make these
So that's what we'll learn today
To process this, we're going to register an Invoker
First let's go to the enemy
On the enemy, we're going to add a component
Type Invoker
There's the NavigationInvoker
You can add it like this, but later
when you make a new enemy
then this isn't there, right?
So we'll create this as a code and add it
If you look here in Navigation, there's Generation Radius
and the Removal Radius
This is what that is
This is the area of newly made path
And after moving and getting far
if it's this much further away
delete the existing area
That's the concept
So I'll set this to about 500 and 800
I'll arrange it like this, then continue working
Then I'll first write this as a code
then continue working on it
Go to the header file of the enemy
I'll make it here
So UPROPERTY
Put EditAnywhere
class UNavigationInvokerComponent
Like this
We'll put NavInvoker here
Should we put Comp?
We'll create this
Then go to the creator of enemy
Right here. Underneath here
we'll continue writing
If you look at the Invoker, there's a dotted line
There's a solid line
It's under the line, right?
Things under here are Actor Components
The ones on top are Scene Components
That's how it is
Since it's underneath, we don't need to attach it
So we'll create it here
Put CreateDefaultSubobject
Here, put UNavigationInvokerComponent
Name it
And we'll need to insert a value here, right?
Earlier, over here
for Generation Radius and Removal Radius
we put 500 and 800
We put 5 m and 8 m
Write it like this
Generation Radius
It's over here
Put it like this
Here, insert the Generation Radius
and the Removal Radius
We'll write 500, 800
And we'll have to add header, right?
I added the header like this
If you take a look
You need to insert it like this
Turn off Unreal, compile, then open again
We'll check if it's applied well
Delete this
Select it, and it's applied well, right?
And we need to do some project settings
In Edit, go to Project Settings
Go all the way down... and here it is
There are two items related to navigation
There's Mesh and System
If you look at Navigation Mesh first
Scroll down
If you look at Runtime
It has an option for Generation
Here, it's set as Static
This is what we talked about earlier
It means it will make the paths ahead of time
But using an Invoker means
we're making it in real-time
So expand it and change it to Dynamic
And go to the Navigation System
If you look in Navigation Enforcing
There's a check box for whether you'll use a Navigation Invoker
Check the box
Those are the two settings to need to make
Come back, save it all
Then this rectangle changed a little
Earlier, all of these were paths
This time, only the area around the enemy is the path
Push the enemy back a little
Then only this area is the path
Execute, and the enemy walks in place
It can't find the player
If I go closer
If I closer, it can find me
If I go further and run away, it can't find me
To make this more smooth
I'll make the enemy move slower than the player
In Enemy Character Movement, we'll decrease the Walk Speed to about 400
Compile, then
We'll have to implement this now
Go to TickMove of EnemyFSM
We'll write it here
To search for the destination
we first have to explore the route
In order to explore
Put auto
We'll put ns. What this means is
the Navigation System
There's something called UNavigationSystemV1
From here, we'll bring GetNavigationSystem
Here, we put World
Put GetWorld
And this is what we're going to use
Ultimately, in ns
There are two types of FindPath, Sync and Async
Async means asynchronous
We're going to process it synchronously
Put Sync
Here, we put a value
If you look here, PathFindingQuery is inserted
Then PathFindingMode is inserted
These are basic things that are included
so we need to make a Query
So FPathFindingQuery
We'll make this variable
Call it Query
And you need to insert that here
Next, if you look in AI
There's something called BuildPathFinding
This is used to actually build the path
Here, there are 4 variables
FAIMoveRequest goes in here
Then Query is inserted
So FAIMoveRequest
We'll need another variable
We'll call this req
Since req is request
AcceptanceRadius goes in here
We'll put 50, as we said earlier
So if it comes within 50 cm around it
it's processed as arrival
Then for the request
we need the destination
Put SetGoalLocation like this
And we'll insert the destination like this
And we need to put that here
Put req here
Then put query like this
Then through the req
the query gets filled in
To use this, you have to add headers
Mine's already added
It's added like this
Add Navigation System as well
If you search here
Like this, this content here
We'll add the header on top
Then we found the path like this
We'll have to process using this
Here, there's a return value
There's something called FPathFindingResult
We'll receive this
We'll receive it as auto r
And if this succeeds
Ah not r, there's r.Result
Use this
Put ==
And this is ENavigationQueryResult
That's this
If you look here
There's success and fail
For Success, what happens?
Tracking happens
Here, since we're heading toward the destination
For destination, if you look here
It's the location of the target, right?
So the destination
since it's the perspective of the enemy
If the player is set as the destination
it just needs to go in that direction
So the content that's previously implemented
will be inserted here as tracking
But for Invoker, in the overall current path
it only checks its own area
So it might be outside the path
In the case of else
the destination is not here
Instead of this, we want to put a random destination
So RandomLocation
We would have to remember the destination, right?
So we'll remember a variable
So RandomLocation
We'll make a variable
Then we'll have to do this first
To use this, to make a random location
we'll declare it in the header
Should we do it at the very bottom?
Like this, as FVector
RandomLocation
It will remember it like this
Then we'll have to fill this in
To fill it in, we'll make a variable
We'll do a bool type
GetRandomLocation
We'll make a function like this
InNavMesh
We'll do this
Then the first factor is the origin
Within a certain radius from the origin
it will mark a point
So FVector origin
Like this
Then float radius
And return the result
Since the return value is bool
Then we'll insert an actual value
and fill this in, so
FVector& like this, then Out
We'll receive the result return value here
OutLocation
We'll make the variable like this
Declare the variable like this
Then we'll make this as an implementation
Make it like this
We need a Navigation System here as well
So put auto ns
In UNavigationSystemV1
GetNavigationSystem
We'll bring it as GetWorld
And in ns
random
Put GetRandom
There are functions here
For Point
GetRandomPointInNavigableRadius
For this, a random value from the overall path
is plotted
Reachable is the location that I can move about
within the random area
the location that it can move to
So we'll bring this
Like this
For parameter, what you need to put for the argument value is
the origin
Insert the origin
Then the radius goes in
The radius, and then
Do FNavLocation &
and we need to put this kind of variable
Then the result from here will be included here
So put FNavLocation
Should we make this the location?
We'll put it in like this
Then it will actually be included here
And this returns bool
Which means there's success and fail
So we'll receive that
bool bResult = like this
And we're going to return this
And if the result is true
If success, then
In OutLoc, what we included
the location value
We'll insert it here
You need to make a function like this
For this function, when it first begins
in BeginPlay
Here, we're going to choose a random location
Since it's origin, put GetActor
since this is component
we'll have to bring it from Me
In Me, GetActorLocation
Bring it like this
For radius, we'll put 500
About 5 m
And we need to put the result
Here, we'll put random location
Then it will fill in here
in RandomLocation
Using this function
we'll fill in this value
Then after filling in like this
Go to TickMove
and we're going to continue implementing this
Then here, we're going to do this
Here, we're going to
first move to a random location
If we arrive
or if there's a problem at that location
then we need to decide a random location again
If there's a problem in the location
choose a random location again
That's what we want to do
So that's why I copied it and brought it
And when it moves, we'll have to see the results
To see if it arrived, we need to know the results
To know the results, we can do this
In reality, MoveToLocation has a return value
So using this return value
we can know the result
Put auto
This is patrol
patrolResult
We'll receive it like this
Oh but we forgot Set
We'll put Set like this
Then since we received patrolResult
we'll compare using this
If we arrived
put patrolResult ==
EPathFollowingRequestResult
If you look here, there's AlreadyAtGoal
Then this mean, if we arrived
or if there's a problem at that location
If either of them are true, we'll do this job
Choosing the random location
So we'll configure it like this
Here, put or
and we'll put another condition
For this condition, if it failed
If it failed, we can't go
So if it's the situation where we can't go
so if we arrived or if there's a problem
and we can't go
then we'll choose the destination with a random location
That's what it means
We'll build it like this
It failed
To use this
we'll have to add header
So come here
We'll add this as header
Add it, and we'll build again
Okay now it succeeded
That's how you should configure it
Let's execute Unreal and see if it works well
During execute, in the keyboard
you know the quotation mark to the left of the Enter key?
Press it, and it appears like this
The blue part over there
is the actual path area
The enemy moves
and it chooses a random location within its path area
And when I go closer
since I'm on its path, it comes toward me
And I'll run away
If I run away
If the distance increases, it doesn't come anymore
It plots a random location again
and it moves to that area
Arrive, attack, and if I run away
it follows
or it patrols
That's how it's processed
The problem is
Here's the problem
When it's coming closer and I shoot it
it slides and comes to me, right?
We'll solve this
If it's shoot by the gun
There's the state, right?
Then this is where the states are processed
In the case of Damage or Die
and during attack, for these cases
We shouldn't Move
So for these three cases
Same thing for Idle
Only when it's TickMove
the AI activates Path Finding
For all others, it should stop
So we'll process that
We can't insert it one-by-one
It's difficult to determine where to work
Basically, for switching states
there's the SetState function
So here, if newState
is not MoveState
then stop AI
Let's process it like that
Then put a simple condition here
If newState is Move
That's not it
newState is
Not Move
So put an exclamation point here
If it's not Move, then stop AI
There's the function StopMovement
We want to stop it
Save it again
Let's see the results after compiling
Go closer
Shoot it, and it stops
It comes again
Even when it attacks, once it gets shot, it stops
Let's summarize the content we learned in this unit
Path Finding using the Navigation System Path Finding System Add AIModule and NavigationSystem module Arrange NavMeshBoundsVolume on the level
Create the path by setting the X and Y value of Brush Setting to cover the entire floor Set the enemy to find the path using AIController
Path Finding and Patrol Function using the Navigation Invoker Path Finding For static path creation, if the size of the map on the level is too big, there are functional issues
Solve it by dynamically creating the path using the Navigation Invoker function
Dynamically create the path in the Navigation related menu of ProjectSettings and activate the Navigation Invoker function
- Set the Navigation Mesh of Project Settings as Dynamic
Check off the Navigation Invoker of Navigation System in Project Settings
Adding the Patrol Function Utilize the UNavigationSystemV1 class
If the destination is on the current path, then travel there. If not, set a random location and travel