Coding the Unity AI

In the previous lesson, we added a NavMesh to a Scene. We also added the NavMesh Agent, which was attached to a soldier model. We want the soldier to move across the NavMesh and reach a specific point. We'll do the moving in this lesson. The mvoing is done with code.

 

AI Code

Create a new C# script. Call it anything you like. (We went for AIEnemy.) Drag and drop the script onto the soldier in the Hierarchy. Double-click your script to open it up in your coding editor.

In order to use the AI libraries, you need to add this using statement at the very top of your code with the others:

using UnityEngine.AI;

Add these variables to the top of your code, but inside of the class.

public Transform dest;
private NavMeshAgent navMesh;
public GameObject player;

The first one is a Transform called dest. This will be that empty game object we set up, Dest-1. We'll drag and drop it into an empty slot in the Inspector. We'll then have its X, Y and Z positions available to us.

The second variable is a NavMeshAgent called navMesh. The NavMeshAgent has a few neat methods, one of which allows you to set the destination for your AI characters.

The third variable is a GameObject we've called player. This will hold our first person controller.

In your Start method, add this line:

navMesh = GetComponent<NavMeshAgent>();

This gets that NavMeshAgent component we added in the Inspector. We're storing it all in the navMesh variable.

Just below the NavMesh line, add this:

navMesh.SetDestination(dest.transform.position);

This is the line that does the work. The SetDestination method allows you to set a destination for your AI characters. In between the round brackets of SetDestination, you need a Vector3. We get the Vector3 from this:

dest.transform.position

The dest will be our cube game object, Dest-1 in the Hierarchy. We just get the position from the transform. The position is the X, Y and Z values - a Vector3.

In your Update method, add this line for the soldier to look at the player:

transform.LookAt(player.transform);

We did this before, in a previous tutorial. It just makes the soldier look at the player.

Your code should look like this:

Unity C# code to set a destination for a Nav Mesh

Save your code and go back to Unity. Make sure that your soldier is selected in the Hierarchy.

Instead of dragging and dropping game object from the Hierarchy onto the Inspector, there is another way.

In the Inspector, click on the tiny circle to the right of the Dest variable in the Script component:

Pointig to the destination variable in the Unity Inspector p

When you click the circle, you'll see a dialog box appear. Scroll down and select the Dest-1 object:

Selecting a transform from a dialog box

Now double-click Dest-1 to assign it to the Dest slot in the Inspector (and to close down the dialog box):

Now do the same for the Player slot. Click the circle. From the dialog box, select the First person controller full item. Double click to assign:

Now play your game. You should see the soldier glide to his destination, like a Gentleman from Hush. (BtVS Season 4E10, and we'd be impressed if you got that reference!)

Of course, if would be nice if he could run to his spot, instead of gliding.

 

Unity AI and Animations

In a previous lesson, we added some animation for run and shoot. We can reuse these. If you haven't done this previous lesson, then you can create the animations here:

Soldier Animations

Select your soldier, if he's not already selected. In the Inspector on the right, notice that he has an Animator but no Controller:

Click the little circle to the right of the Controller item. From the dialog box that appears, select the Animation Controller you created previously (it was called AC-Soldier):

Close the dialog box down and you should see that the controller you selected has been added:

Now we can get this Animator with code and play whichever animation we want.

So, go back to your code. Add this variable with the other three:

private Animator anim;

In the Start method, and just before the SetDestination line, add these two lines:

anim = GetComponent<Animator>();
anim.Play("Run");

Your code should look like this, with the new lines highlighted:

Unity C# code to get an animation for the AI

We're just getting the Animator component attached to the soldier. Then we play the Run animation we set up.

Save your code and go back to Unity. Play your game and you should see the soldier running to his spot:

3D model running to an AI destination

You can change the speed of the soldier through the Nav Mesh Agent component you added.

With the soldier selected, expand the Nav Mesh Agent component. Change the Speed to anything you like. While you're there, change the Stopping Distance to 0.1, as we'll need this next:

The Speed and Stopping distances highlighted in the Nav Mesh Agent

We want to switch from the running animation to the shooting animation. So we need to detect just when the soldier has reached his destination.

Go back to your code. In the Update method, add this if statement just below the LookAt line:

if (navMesh.remainingDistance < navMesh.stoppingDistance)
{

anim.Play("Shoot");

}

Your code should look like this:

Unity C# code to detect when an AI character has reached his destination

You've already told Unity where the soldier should go with the SetDestination line. The NavMesh has a property called remainingDistance and a property called stoppingDistance. When the remainingDistance to the destination is less than the stoppingDistance then we can say that the soldier has reached his destination. In which case, stop running and shoot at the player. That's all the if statement does - plays the Shoot animation when the soldier gets to where he's supposed to go.

Save your code and go back to Unity. Play your game. Watch the soldier run forward and the stop on his spot. He should then stop running and start firing.

Now let's add another soldier to the scene.

Select your soldier in the Hierarchy. Right-click and select Duplicate from the menu. Or press CTRL + D on your keyboard as a shortcut. Rename it to Soldier2. Now place the new soldier on the right. Place him at these Position and Rotation values in the Inspector:

Position

X: 9
Y: 0
Z: -1

Rotation

X: 0
Y: 270
Z: 0

Also, duplicate the Dest-1 item. Rename it to Dest-2. Move it to these Position values in the Inspector:

Position

X: 1.3
Y: 0.01
Z: -5

It will look like this, in Scene view (we've added a red material to our Dest-2 object):

Two characters placed on the Nav Mesh in Unity

Now click on your Soldier2 to select it. In the Inspector, click the little circle again to the right of Dest. From the dialog box, select Dest-2 as the Transform:

Play your game and you should see both soldiers run to their positions and start shooting. Soldier2 will look a little awkward getting to his spot, but that's the Unity AI for you - it's not perfect!

One thing to notice, though, is that Soldier2 doesn't go to his spot via the shortest route. So he's not cutting across the grass. He's not doing this:

Scene view showing the shortest route an AI character could take

He's sticking to the grey areas, the one's we baked for our NavMesh. He's doing this (sort of):

Unity Scene view showing the actual route an AI character takse

OK, now let's put some obstacles in the path of our soldiers. We'll do that in the next lesson below.

<--Back to the Unity 3D Course Contents Page