Creating a simple AI on C # in Unity

Original author: Lance Talbert
  • Transfer
image

Almost any game requires an artificial intelligence (AI) interacting with the user, most often in the form of a force hostile to the player. In some cases, the AI ​​should help the player, in others - to fight him, but all computer-controlled characters have some similarities. Depending on the requirements of the project, the AI ​​may use simple or complex behaviors. Such requirements may be diplomacy with another player or just wandering back and forth on the platform. Be that as it may, it is necessary to ensure that the AI ​​performs its work with high quality.

In this project I will demonstrate a very simple artificial intelligence. Suppose we create a game in which a player must sneak close to an enemy headquarters. When a player is noticed by a tracking camera, enemies are created nearby and for a short period of time they chase the player. That is what we implement in the project at the simplest level. After completing the project, you will receive a player’s managed object, a circle used as an enemy’s camera, and an enemy object that will chase the player when a camera object reports its presence.

Training


First we need to create a 3D project. Click the New button at the top of the window after launching Unity, as shown in Figure 1.


Figure 1: Create a new project.

Name your project AI and make sure it is a 3D project. After selecting a place on your computer to store the project, click on the Create Project button below, shown in Figure 2.


Figure 2: Project Settings Screen

After creating a project, we first need to set up folders in the Assets window to organize our work. Right-click on the Assets window and select Create → Folder to create a new folder. Name this folder Materials . Then create a second folder and name it Scripts . Figure 3 shows how it should look.


Figure 3: Creating a new folder

After all this, the Assets window should look like that shown in Figure 4.


Figure 4: Assets window .

Next, create a floor on which all objects will stand. In the Hierarchy window, select Create → 3D Object → Plane to create a plane object that will be used as the floor.


Figure 5: Creating a Plane object.

Name this Floor object and change its X Scale value to 7, and the Z Scale value to 3. Then the Inspector window with the selected Floor object should look like that shown in Figure 6.


Figure 6: Setting the properties of the Floor object .

Now we need to create a new material for Floor to distinguish it from the rest of the objects that will be placed in the scene. In the Materials folder of the Assets window, create a new material by right-clicking on the Assets window and selecting Create → Material .


Figure 7: Creating a New Material

Once completed, name the material Floor .


Figure 8: Floor material .

At the top of the Inspector window with the selected Floor material, select a color picker.


Figure 9: the choice of color picker.

Of course, you can choose any color for the floor, but in this example I chose a red-brown color, as shown in Figure 10.


Figure 10: color picker.

Select the Floor object in the Hierarchy window , and in the Mesh Renderer component, select the small arrow next to Materials .


Figure 11: preparation for changing the material.

Drag Floor material from the Assets window to the Element 0 field of the Mesh Renderer component in the Inspector window .


Figure 12: Setting the Floor material as the material of the Floor object .

After finishing with the Floor object , we must create around the wall area so that the player cannot fall off the edge. Again, go to Create → 3D Object → Plane to create a new plane. Name this plane Wall and set it to the same dimensions as Floor , i.e. X Scale with a value of 7 and Z Scale with a value of 3. Then create three more walls by selecting the object and pressing Ctrl + D three times. After that we place the walls around floor in accordance with the data from the table.

Title
Position X
Position y
Position z
Rotation x
Rotation z
Wall
-35
21
0
0
-90
Wall (1)-one
eleven
-15
90
0
Wall (2)
-one
eleven
13.5
-90
0
Wall (3)
34
21
0
0
90

Table 1: Positions and Turns of All Wall Objects .

Having completed all this, you need to change the position of the camera so that it looks at the floor above. Select the Main Camera object and set the Y Position to 30, the Z Position to 0, and the X Rotation to 80.


Figure 13: Configure the camera object.

The scene is prepared, so it's time to create a player character. In the Hierarchy window, click on Create → 3D Object → Sphere to create a sphere object. Name this object Player , and then click on the Add Component button at the bottom of the Inspector window .


Figure 14: Adding a new component.

Now find the rigidbody . After that, select the Rigidbody component from the list and add the Rigidbody to the Player object .


Figure 15: Adding the Rigidbody component .

Next, you need to assign the player a tag, which later will come in handy to us in the code. Click the Tag drop-down menu in the upper left corner of the Inspector window and select the Player tag .


Figure 16: setting a new tag.

We need to set the player's position so that he is not under the Floor object . In the example, I placed the player in the upper left corner with the X position equal to 26, the Y Position equal to 1, and the Z position equal to -9.


Figure 17: player placement.

For our future code to work correctly, we, of course, need to attach it to the object. Go to the Hierarchy window again and this time select Create → 3D Object → Cube . Let's name this cube Guard , add the Rigidbody component and the NavMesh Agent component to it using the Add Component button in the Inspector window . Next, put it somewhere in the upper left corner of the scene. After this, the Inspector window of the Guard object will look as follows:


Figure 18: The Guard object in the Inspector window .

And this object should be located like this:


Figure 19: Placement of the Guard object .

Finally, we will need an object used as the “eye” of the Guard object , which will notify the Guard that the player touches it. The last time go to the Hierarchy window and select Create → 3D Object → Sphere to create another sphere object. Name this object Looker . This time we don’t need to add any other components to it. However, we will change the size of the object. With the Looker selected , change the following variables of the Transform component in the Inspector window .

  • Scale X on 9.
  • Scale Y to 0.5.
  • Scale Z to 9.

After that, place the Looker object so that it is located in the middle upper part of the floor, as shown in Figure 20.


Figure 20: Layer object placement.

Now is the right time to give the Looker a unique material so that it is noticeable that it should be avoided. In the Materials folder of the Assets window, right-click and create a new material. Call it a looker and give it a bright red color. After that, assign this material as a material for the Looker object to change its color. After that, the scene should look like this:


Figure 21: Looker object with new material.

The only thing left for us is to create a navigation mesh for the Guard through which it can move. At the top of the Unity editor is the Window menu . Choose Window → Navigation to open the Navigation window shown in Figure 22.


Figure 22: Navigation window .

Select the Floor object in the Hierarchy , and then in the Navigation window check the Navigation Static box .


Figure 23: Navigation Static .

Next, select the Bake option at the top of the window.


Figure 24: Switch to the Bake menu .

The Bake menu opens where you can change the properties of the navigation mesh we are going to create. In our example, nothing needs to be changed. Just click on the Bake button in the lower right.


Figure 25: Creating a new navigation mesh.

At this point, Unity will ask you to save the scene. Save it, after which the navigation mesh will be created. Now the scene will look like this:


Figure 26: The current scene with the added navigation mesh.

Now everything is configured in Unity, so it’s time to create the scripts needed for the project to work. In the Assets window, right-click and select Create → C # Script . Call this script Player . Repeat this operation two more times, creating scripts with the names Guard and Looker .


Figure 27: Creating a new script.

After this, the Scripts folder in the Assets window will look like this:


Figure 28: Scripts folder .

First we start writing the script for the Player . Double-click the Player script in the Assets window to open Visual Studio and start creating code.

Code


The Player script is quite simple; all it does is allow the user to move the ball object. Under the class declaration, we need to get a reference to the Rigidbody component that we previously created in the project.

private Rigidbody rb;

Immediately after that, in the function Start we will order to make Unity the current component Rigidbody object Player value rb .

rb = GetComponent<Rigidbody>();

After this, the Player script will look like this:


Figure 29: Player script currently.

Now that the rb value is assigned, we need to allow the Player object to move when we press the arrow keys. To move the object, we will use physics, applying force to the object when the user presses the arrow keys. To do this, simply add the following code to the Update function :

if (Input.GetKey(KeyCode.UpArrow))
            rb.AddForce(Vector3.forward * 20);
if (Input.GetKey(KeyCode.DownArrow))
            rb.AddForce(Vector3.back * 20);
if (Input.GetKey(KeyCode.LeftArrow))
            rb.AddForce(Vector3.left * 20);
if (Input.GetKey(KeyCode.RightArrow))
            rb.AddForce(Vector3.right * 20);

At this point, we completed the Player script . The finished script will look like this:


Figure 30: Ready Player Script .

Save your work and return to Unity. This time, select the Guard script in the Assets window . To make the code for Guard work, you need to add a using construct to the top of the script.

using UnityEngine.AI;

Next, we declare the following variables immediately after the class declaration.

public GameObject player;
private NavMeshAgent navmesh;

The value of the variable player object Guard object is used Player Get . It will be useful to us later when we order the Guard object to pursue the player. Then, the variable navmesh is declared to get the component NavMeshAgent object. We use it later when the Guard starts chasing the player after finding out that the player is touching the Looker object . In the Start function, we need to set the object's NavMesh Agent component as the value of the navmesh variable :

navmesh = GetComponent<NavMeshAgent>();

Then in the Update function we add a single line of code:

navmesh.destination = player.transform.position;

This line specifies the destination for the Guard object . In our case, it will take the current position of the Player object and move to this point. After triggering the object will constantly pursue the player. The question is how the triggering process is performed? It will not be encoded in the Guard script , but in the Looker script . Before proceeding to the Looker script, look at Figure 31 to verify your Guard script code .


Figure 31: Ready Guard script .

Inside Looker, we again need to declare the following variables:

public GameObject guard;
privatefloat reset = 5;
privatebool movingDown;

After that, we will comment out the Start function , which we do not need in this script. Go to the Update function and add the following code:

if (movingDown == false)
            transform.position -= new Vector3(0, 0, 0.1f);
        else
            transform.position += new Vector3(0, 0, 0.1f);
if (transform.position.z > 10)
            movingDown = false;
elseif (transform.position.z < -10)
            movingDown = true;
reset -= Time.deltaTime;
if (reset < 0)
{
            guard.GetComponent<Guard>().enabled = false;
            GetComponent<SphereCollider>().enabled = true;
}

This is where the main project activities take place, so let's analyze the code. First, depending on the value of the movingDown boolean , the object to which this script is attached will move up or down. Once it reaches a certain point, it will change direction. Further Looker reduce the value of the reset on the basis of real time. Once the timer is less than zero, he'll take the script Guard of the object Guard and unplug it, and then the object Guard starts to move to the last known before momenrta position player, and then stop. Lookeralso turns on its collider again so that the whole process can begin anew. Now our script looks like this:


Figure 32: Looker script .

Speaking of colliders: the time has come to create a collision code that resets the Looker timer and includes the Guard script . In the Update function, create the following code:

privatevoidOnCollisionEnter(Collision collision)
{
        if (collision.gameObject.tag == "Player")
        {
            guard.GetComponent<Guard>().enabled = true;
            reset = 5;
            GetComponent<SphereCollider>().enabled = false;
        }
}

OnCollisionEnter Unity automatically recognizes as a collision code, and therefore executes it when a collision occurs with another object. In our case, it first checks if the object that is encountered has a Player tag . If not, it ignores the rest of the code. Otherwise, it turns on the Guard script , sets the reset timer to 5 (that is, five seconds), and turns off its collider so that the player can still move through the object and not accidentally get stuck in the Looker object . The function is shown in Figure 33.


Figure 33: Collision Code for Looker.

On this all project code is ready! You can do a couple of things before you finish the project. Save all the work and go back to Unity.

Completion of the project


To complete the project, we just need to attach the scripts to the corresponding objects and set several variables. First, go from the Navigation window to the Inspector window :


Figure 34: Switch to the Inspector window .

After that, let's start with the Player object . Select it in the Hierarchy window , and at the bottom of the Inspector window, click on the Add Component button and add the Player script . This completes the Player object .


Figure 35: Player script component .

Next, select the object Guard . As before, attach the Guard script to the object. This time we will need to tell the Guard who the player is. To do this, drag the Player object from the Hierarchy to the Player field of the Guard script component , as shown in Figure 36.


Figure 36: make the Player object the value of the Player field .

We also need to disable the Guard script . In our project, the Guard will pursue the player after the inclusion of his script. This Guard script should only be enabled after the player touches the Looker object . All you need to do is uncheck the box next to the Guard (Script) text in the component:


Figure 37: disabling the Guard script .

Finally, go to the Looker object and attach the Looker script to it . This time, the Looker object will need the Guard object as the value of its Guard variable . Just as we assigned the object Player variable Player script Guard , we will do the same with the object Guard and script Looker . Drag Guard from Hierarchy into the Guard field of the Looker script. And this project is completed! Click the Play button at the top of the Unity editor to test your project.


Figure 38: testing the project.

Try moving the Player object to the Looker object (don't forget that the movement is done by arrows!). Notice that after this the Guard object will start chasing the player. He will continue the pursuit for about 5 seconds, after which he will surrender.


Figure 39: Completely finished project in action.

Conclusion


This AI is very simple, but you can easily expand it. Suppose if we imagine that the Looker object is a camera, and the guard looks through it to find you, it will be logical to give the Guard object its own pair of eyes. The player may pass near the cameras, but they must take into account the eyes of the guard. You can also combine this project with the concept of finding a path : give the guard the path that he will follow, thus creating a more interesting environment for the player.

Such a simple AI can be developed in many different ways. You may not want to do the above and decide to do something of your own. I advise you to experiment, perhaps you will have the idea of ​​an interesting project that should be completed.

Also popular now: