From the course: Cert Prep: Unity Certified Associate Game Developer Scripting with C#

Creating the Patrol state

- [Instructor] In the previous chapter we started to create our finite state machine project. And in this chapter, we're going to complete that project. We'll focus specifically here on the NPC character. We'll start in this video by focusing on the patrol state for the NPC. In the patrol state, the NPC can move around the level and if they see the player character they'll change from patrolling to chasing. Now, while they are patrolling they're going to be selecting random destinations to move to. They'll move to a random destination and when they get there, they'll change to a new destination and so on. Now, to get started at creating the patrol state I'm going to give our NPC character a field of view, a complete area inside the world where they can see being their eye point. So I'm going to double-click the enemy character to focus our viewport onto the enemy here. And then selecting the enemy character, I'm going to move to the menu and choose Component, Physics, and then select Box Collider from the menu. This Box Collider will represent their field of view. I'll move along to the Inspector here to tweak the properties for the Box Collider. Now, because this is acting as a field of view and not a collider itself, I'm going to change this and enable Is Trigger here. In addition to that, I'm going to use the Size and the Center fields to resize the collider to represent the field of view for the NPC. In this case, I'm going to move to the Z field, click and drag to increase the length of this. I'm going to do the same for the X field too, and also the Y. Now, because the character can't see behind themselves, they haven't got eyes in the back of their head, I'm going to use the Center parameter here in the Z field to increase the field of view for the NPC character. I want to be careful not to make this too long, because otherwise they're going to be able to see the player from practically anywhere. So now in resizing this, I've represented the field of view for the NPC character. Now, in addition to this, I also want to create some waypoints inside the scene. These waypoints are the random destinations that the NPC is going to be choosing between when they're choosing where to move. Now, to create these waypoints, I'm simply going to use empty objects to represent their locations. To get started at that I'm going to move to the menu here, choose Game Object, create Empty, and I'm going to rename the empty to Waypoints. I'm going to center it to the world origin. It's not crucial that you do that, but I think it's kind of neat to do that. In addition, I'm going to create some child objects. This object here, the Waypoints object, is just going to be a container for all the waypoints we could potentially add. So I'm going to right-click on Waypoints, choose Create Empty, and I'm going to rename that to Waypoint. Now, because this is an empty object we can't see it inside the viewpoint if we de-select it. But I want to make this visible, so we can easily see it. To do that, I'm going to move to the Inspector to the top left-hand side, click on the cube, and from the cube icon, select the orange tag, so I can easily see that inside the viewpoint. The next thing that I want to do is to position this waypoint to be at the location that I want to have for our very first waypoint. So I'm going to place it around about here, close to the floor inside the very first room. Now, all the waypoints in this level will need to be tagged as waypoints, so that inside script I can easily find them if I need to. So I'm going to move to the Tag field where currently this object is untagged. If I click on the drop-down, you can see that we don't have a tag for waypoint. Now, I could try to use the Respawn tag but I'm going to create a completely new tag. So I'm going to move to the bottom and select Add Tag and then click the plus icon to add a new tag. I'm going to call this tag Waypoint and press Enter on the keyboard. Then I'll select the waypoint in the scene and make sure for the Tag field that I click in the drop-down and I assign it the Waypoint tag specifically. Then I'll select the object and I'm going to duplicate it with Control + D or Command + D on a Mac. So I'm going to choose Command + D and simply move that waypoint to a new location, which is going to be the position for the second waypoint. I'll move that to the left just a little bit. Going to duplicate this one too, move it to maybe around about here somewhere. Duplicate again and move it to this side round about here, maybe move it up a little bit. And duplicate that one over to here. And I'm just selecting points at random pretty much. Duplicate this one and move it to here. And finally, duplicate another one, so we have a good selection of waypoints around the level that potentially the NPC could move to when it's patrolling. Now, let's create the patrol state itself inside our script file. To do this I'm going to be working on the AI state script that we created previously. By moving to the Scripts folder, and here we have the AI Chase Script. I'll double-click that to open it inside Visual Studio. And here's our AI Chase Script inside Visual Studio. The first thing that I want to do is to create the state patrol. That is fundamentally the behavior that the NPC will be showing when they're patrolling. To do this I'm going to use a coroutine. So I'm going to move down slightly further and create a completely new coroutine. I'll choose public IEnumerator, and I'll call this StatePatrol, and here we're going to be defining the patrol behaviors. The first thing that we want to do when we're patrolling is to get a list of all those waypoints in the level, because we're going to be choosing one of them at random. To do this I'm going to create a list of waypoints. So I'm going to use an array. GameObject array Waypoints = and we're going to find our waypoints by their tag. So I'm going to choose GameObject.FindObjects, notice the plural here, FindObjectsWithTag, and I'm going to be finding the WaypointsObjects, like so. In the next line, I'm going to be choosing one of the waypoints at random from that list. So I'm going to choose GameObjects, CurrentWaypoint = and here is where I'm going to choose them at random. So from that list, I'm going to select Waypoints, and then inside the array index here we're going to be choosing a random number by using Random.Range it's going to be a random range between zero and then the maximum, which is going to be the length of the array, like so. Now, in choosing a waypoint at random, the next thing I want to do is I want to define a distance to the target, to the waypoint itself. This is going to define how close the NPC should get to the waypoint before it chooses another one to move to. So I'm going to choose float TargetDistance, and I'll set that to the initial value of 2. And now I'll create a loop, which means that the NPC is going to continually repeat the patrolling behavior. So I'm going to choose while CurrentState = AISTATEPATROL. While the AI state is currently in the patrol state, we should continue the patrolling behaviors. You'll notice slightly higher up at line 11 we have the CurrentState variable, which is keeping track of the current state that we're in. By default it's set to the patrol state, but, of course, it could be patrol, chase, or attack. So inside the while loop here is where we want to continually move towards the waypoint that we have selected. So I'm going to choose ThisAgent.SetDestination and we're going to be moving towards the selected waypoint by choosing CurrentWaypoint.transform.position. Now, after that we want to check how close are we to the current waypoint. If we are within the target distance then we should choose a new waypoint to move towards. We can check the distance between any two points by using the function Vector3.Distance. Here's how we do that. We can choose if Vector3.Distance and we can plug in our two inputs. The first input should be the position of the NPC character and that's represented by transform.position. Now, the second value is the position at the waypoint. And that is CurrentWaypoint, which is represented here, CurrentWaypoint.transform.position. And if the distance between those two points is less than the TargetDistance that we've set, then we need to select a new, random waypoint. We've already seen the code to do that. It's here at line 22. Current waypoint equals a random waypoint. The last thing that we need to have on this line here inside the while loop to prevent this from looping infinitely is a yield statement that pauses for one frame for every iteration of the loop. To do that I'm going to write yield return null. And then I'm going to save that code. We've now defined our state patrol coroutine. And the last thing we need to do is to initiate that coroutine when the level begins to put the NPC into the patrol state. To do that I'm going to use the Start function here by choosing void Start and inside here I'm going to initiate the patrol coroutine simply by using StartCoroutine to initiate StatePatrol. And now I'm going to choose File and Save again and go back to Unity to test out the code that we have just created. In very few lines, using a pretty short coroutine, the StatePatrol here, alongside the initiation of it here, we've created some pretty straightforward behavior and yet it's going to have a really important effect to how intelligent our NPC appears. So I'm going to make sure I go back to the scene here. And actually, before I initiate the code, there's just one thing I want to check. Just to make sure that we haven't made a mistake when it relates to tags. If I select one of my waypoints you can see that the tag is actually Waypoint, singular. But if I go back to my code here, you'll see that I'm actually searching for the object based on the plural. So I want to just delete that S and resave. Very easy mistake to make that. Let's just go back to Unity here, our code recompiles. I'm going to grab the Game tab and move that side-by-side with the Scene tab, so that I can take a look at the NPC character moving around the scene and choosing waypoints. So I'm going to press play on the toolbar to test out our waypoint functionality. And there straight away the NPC is moving to a randomly selected waypoint. On reaching there, they're then selecting a new waypoint and moving towards that one. And then on arriving at that waypoint, they'll select another one. You can see here they've chosen waypoint six and now they're moving towards waypoint four maybe. No, actually could it be waypoint three? Looks like it's waypoint two. No, it's all the way down to the original waypoint, and then on reaching there it's going to select another random waypoint. Great, that's the random selection behavior in practice here where the NPC now has the ability to choose between different waypoints in the scene, to select one of those random, and move towards it. We still don't have the functionality to test whether the NPC can see the player character yet, and whether they need to move to chase. The chase state is what we're going to focus on in the next video.

Contents