Chapter 5. Enemy and Friendly AIs

Artificial Intelligence, also known as AI, is something that you'll see in every video game that you play. First-person shooter, real-time strategy, simulation, role playing games, sports, puzzles, and so on, all have various forms of AI in both large and small systems. In this chapter, we'll be going over several topics that involve creating AI, including techniques, actions, pathfinding, animations, and the AI manager. Then, finally, we'll put it all together to create an AI package of our own.

In this chapter, you will learn:

  • What a finite state machine is
  • What a behavior tree is
  • How to combine two AI techniques for complex AI
  • How to deal with internal and external actions
  • How to handle outside actions that affect the AI
  • How to play character animations
  • What is pathfinding?
  • How to use a waypoint system
  • How to use Unity's NavMesh pathfinding system
  • How to combine waypoints and NavMesh for complete pathfinding

AI techniques

There are two very common techniques used to create AI: the finite state machine and the behavior tree. Depending on the game that you are making and the complexity of the AI that you want, the technique you use will vary. In this chapter, we'll utilize both the techniques in our AI script to maximize the potential of our AI.

Finite state machines

Finite state machines are one of the most common AI systems used throughout computer programming. To define the term itself, a finite state machine breaks down to a system, which controls an object that has a limited number of states to exist in. Some real-world examples of a finite state machine are traffic lights, television, and a computer. Let's look at an example of a computer finite state machine to get a better understanding.

A computer can be in various states. To keep it simple, we will list three main states. These states are On, Off, and Active. The Off state is when the computer does not have power running it, the On state is when the computer does have power running it, and the Active state is when someone is using the computer. Let's take a further look into our computer finite state machine and explore the functions of each of its states:

State

Functions

On

  • Can be used by anyone
  • Can turn off the computer

Off

  • Can turn on the computer
  • Computer parts can be operated on

Active

  • Can access the Internet and various programs
  • Can communicate with other devices
  • Can turn off the computer

Each state has its own functions. Some of the functions of each state affect each other, while some do not. The functions that do affect each other are the functions that control what state the finite state machine is in. If you press the power button on your computer, it will turn on and change the state of your computer to On. While the state of your computer is On, you can use the Internet and possibly some other programs, or communicate to other devices such as a router or printer. Doing so will change the state of your computer to Active. When you are using the computer, you can also turn off the computer by its software or by pressing the power button, therefore changing the state to Off.

In video games, you can use a finite state machine to create AI with a simple logic. You can also combine finite state machines with other types of AI systems to create a unique and perhaps more complex AI system. In this chapter, we will be using finite state machines as well as what is known as a behavior tree.

The behavior tree form of the AI system

A behavior tree is another kind of AI system that works in a very similar way to finite state machines. Actually, behavior trees are made up of finite state machines that work in a hierarchical system. This system of hierarchy gives us great control over an individual, and perhaps many finite state systems within the behavior tree, allowing us to have a complex AI system.

Taking a look back at the table explaining a finite state machine, a behavior tree works the same way. Instead of states, you have behaviors, and in place of the state functions, you have various finite state machines that determine what is done while the AI is in a specific behavior. Let's take a look at the behavior tree that we will be using in this chapter to create our AI:

The behavior tree form of the AI system

On the left-hand side, we have four behaviors: Idle, Guard, Combat, and Flee. To the right are the finite state machines that make up each of the behaviors. Idle and Flee only have one finite state machine, while Guard and Combat have multiple. Within the Combat behavior, two of its finite state machines even have a couple of their own finite state machines.

As you can see, this hierarchy-based system of finite state machines allows us to use a basic form of logic to create an even more complex AI system. At the same time, we are also getting a lot of control by separating our AI into various behaviors. Each behavior will run its own silo of code, oblivious to the other behaviors. The only time we want a behavior to notice another behavior is either when an internal or external action occurs that forces the behavior of our AI to change.

Combining the techniques

In this chapter, we will take both of the AI techniques and combine them to create a great AI package. Our behavior tree will utilize finite state machines to run the individual behaviors, creating a unique and complex AI system. This AI package can be used for an enemy AI as well as a friendly AI.

Let's start scripting!

Now, let's begin scripting our AI! To start off, create a new C# file and name it AI_Agent. Upon opening it, delete any functions within the main class, leaving it empty. Just after the using statements, add this enum to the script:

public enum Behaviors {Idle, Guard, Combat, Flee};

This enum will be used throughout our script to determine what behavior our AI is in. Now let's add it to our class. It is time to declare our first variable:

public Behaviors aiBehaviors = Behaviors.Idle;

This variable, aiBehaviors, will be the deciding factor of what our AI does. Its main purpose is to have its value checked and changed when needed. Let's create our first function, which will utilize one of this variable's purposes:

void RunBehaviors()
{
  switch(aiBehaviors)
  {
  case Behaviors.Idle:
    RunIdleNode();
    break;
  case Behaviors.Guard:
    RunGuardNode();
    break;
  case Behaviors.Combat:
    RunCombatNode();
    break;
  case Behaviors.Flee:
    RunFleeNode();
    break;
  }
}

What this function will do is check the value of our aiBehaviors variable in a switch statement. Depending on what the value is, it will then call a function to be used within that behavior. This function is actually going to be a finite state machine, which will decide what that behavior does at that point. Now, let's add another function to our script, which will allow us to change the behavior of our AI:

void ChangeBehavior(Behaviors newBehavior)
{
  aiBehaviors = newBehavior;

  RunBehaviors();
  
}

As you can see, this function works very similarly to the RunBehaviors function. When this function is called, it will take a new behaviors variable and assign its value to aiBehaviors. By doing this, we changed the behavior of our AI. Now let's add the final step to running our behaviors; for now, they will be empty functions that act as placeholders for our internal and external actions. Add these functions to the script:

void RunIdleNode()
{

}

void RunGuardNode()
{

}
  
void RunCombatNode()
{

}
  
void RunFleeNode()
{

}

Each of these functions will run the finite state machines that make up the behaviors. These functions are essentially a middleman between the behavior and the behavior's action. Using these functions is the beginning of having more control over our behaviors, something that can't be done with a simple finite state machine.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.134.151