Reader small image

You're reading from  Unity 5.x Game AI Programming Cookbook

Product typeBook
Published inMar 2016
PublisherPackt
ISBN-139781783553570
Edition1st Edition
Tools
Right arrow
Author (1)
Jorge Palacios
Jorge Palacios
author image
Jorge Palacios

Jorge Palacios is a software and game developer with a BS in computer science and eight years of professional experience. He's been developing games for the last five years in different roles, from tool developer to lead programmer. Mainly focused on artificial intelligence and gameplay programming, he is currently working with Unity and HTML5. He's also a game-programming instructor, speaker, and game-jam organizer.
Read more about Jorge Palacios

Right arrow

Chapter 4. Coordination and Tactics

In this chapter, we will learn techniques for coordination and devising tactics:

  • Handling formations

  • Extending A* for coordination: A*mbush

  • Creating good waypoints

  • Analyzing waypoints by height

  • Analyzing waypoints by cover and visibility

  • Exemplifying waypoints for decision making

  • Introducing influence maps

  • Improving influence with map flooding

  • Improving influence with convolution filters

  • Building a fighting circle

Introduction


As we will see, this is not a chapter focused on a sole subject, but rather a chapter that has its own original recipes and also learns from previous recipes in order to create new or improved techniques.

In this chapter, we will learn different recipes for coordinating different agents into one organism, such as formations and techniques that allow us to make tactical decisions based on graphs (such as waypoints) and influence maps. These techniques use different elements from the previous chapters and recipes, especially from the graph construction and path finding algorithms found in Chapter 2, Navigation.

Handling formations


This is a key algorithm for creating flocks or a group of military agents. It is designed to be flexible enough to give you the chance to create your own formations.

The end result from this recipe will be a set of target positions and rotations for each agent in the formation. Then, it is up to you to create the necessary algorithms to move the agent to the previous targets.

Note

We can use the movement algorithms learnt in Chapter 1, Movement, in order to target those positions.

Getting ready

We will need to create three base classes that are the data types to be used by the high-level classes and algorithms. The Location class is very similar to the Steering class and is used to define a target position and rotation given the formation's anchor point and rotation. The SlogAssignment class is a data type to match a list's indices and agents. Finally, the Character class component holds the target Location class.

The following is the code for the Location class:

using UnityEngine...

Extending A* for coordination: A*mbush


After learning how to implement A* for path finding, we will now use its power and flexibility to develop some kind of coordinated behavior in order to ambush the player. This algorithm is especially useful when we want a non-expensive solution for the aforementioned problem, and one that is also easy to implement.

This recipe sets the path for every agent to be taken into account when it comes to ambushing a given vertex or point in the graph.

Getting ready

We need a special component for the agents called Lurker. This class will hold the paths that are to be used later in the navigation process.

The following is the code for Lurker:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Lurker : MonoBehaviour
{
    [HideInInspector]
    public List<int> pathIds;
    [HideInInspector]
    public List<GameObject> pathObjs;

    void Awake()
    {
        if (pathIds == null)
            pathIds = new List...

Creating good waypoints


There are times when the number of waypoints must be reduced at a certain point during the game or just for memory constraints. In this recipe, we will learn a technique called condensation that helps us deal with this problem, forcing the waypoints to compete with each other given their assigned value.

Getting ready

In this recipe, we will deal with static member functions. It is important that we understand the use and value of static functions.

How to do it…

We will create the Waypoint class and add the functions for condensing the set of waypoints.

  1. Create the Waypoint class, deriving not only from MonoBehaviour, but also from the IComparer interface:

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    
    public class Waypoint : MonoBehaviour, IComparer
    {
        public float value;
        public List<Waypoint> neighbours;
    }
  2. Implement the Compare function from the aforementioned interface:

    public int Compare(object a, object b)
    {
        Waypoint wa...

Analyzing waypoints by height


This recipe lets us evaluate a waypoint according to its position. Strategically speaking, lower positions are at a disadvantage. In this case, we will use a flexible algorithm to get the quality of a waypoint, given the heights of its surroundings.

Getting ready

This recipe is simple enough, so there is no extra content to be aware of. The algorithm is flexible enough to receive a list of positions, which is given by the waypoint's neighbors or just the complete graph of waypoints. The surroundings heuristic is kept outside for our perusal and it gives the game's specific design.

How to do it…

We will implement a function to evaluate a location given its height and its surrounding points:

  1. Declare the function for evaluating the quality:

    public static float GetHeightQuality (Vector3 location, Vector3[] surroundings)
    {
        // next steps
    }
  2. Initialize the variables for handling the computation:

    float maxQuality = 1f;
    float minQuality = -1f;
    float minHeight = Mathf.Infinity...

Analyzing waypoints by cover and visibility


When dealing with military games, especially FPS, we need to define a waypoint value, by its capacity, to be a good cover point with the maximum visibility for shooting or reaching other enemies visually. This recipe helps us compute a waypoint's value given these parameters.

Getting ready

We need to create a function for checking whether a position is in the same room as others:

public bool IsInSameRoom(Vector3 from, Vector3 location, string tagWall = "Wall")
{
    RaycastHit[] hits;
    Vector3 direction = location - from;
    float rayLength = direction.magnitude;
    direction.Normalize();
    Ray ray = new Ray(from, direction);
    hits = Physics.RaycastAll(ray, rayLength);
    foreach (RaycastHit h in hits)
    {
        string tagObj = h.collider.gameObject.tag;
        if (tagObj.Equals(tagWall))
            return false;
    }
    return true;
}

How to do it…

We will create the function that computes the quality of the waypoint:

  1. Define the function...

Exemplifying waypoints for decision making


Just like we learned with decision-making techniques, sometimes it is not flexible enough to just evaluate a waypoints' value, but rather a more complex condition. In this case, the solution is to apply techniques learned previously and couple them into the waypoint for attacking that problem.

The key idea is to add a condition to the node so that it can be evaluated, for example, using a decision tree and developing more complex heuristics for computing a waypoint's value.

Getting ready

It is important to revisit the recipe that handled state machines in the previous chapter before diving into the following recipe.

How to do it…

We will make a little adjustment:

  1. Add public Condition to the Waypoint class:

    public Condition condition;
  2. Now, you'll be able to easily integrate it into decision-making techniques using derived condition classes such as ConditionFloat.

How it works…

The pseudo-abstract Condition class, which we learned about previously, has a member...

Influence maps


Another way to use graphs is to represent how much reach or influence an agent, or in this case a unit, has over an area of the world. In this context, influence is represented as the total area of a map an agent, or a group of agents of the same party, covers.

This is a key element for creating good AI decision mechanisms based on the military presence in real-time simulation games, or games where it is important to know how much of the world is taken by a group of agents, each representing a given faction.

Getting ready

This is a recipe that requires the experience of graph building, so it is based on the general Graph class. However, we will need to derive it from a specific graph definition, or define our own methods to handle vertices and the neighbors retrieval logic, as learned in Chapter 2, Navigation.

We will learn how to implement the specific algorithms for this recipe, based on the Graph class general functions and the Vertex class.

Finally, we will need a base Unity...

Improving influence with map flooding


The previous influence computation is good when dealing with a simple influence that is based on individual units helping a faction. However, this could lead to holes in the map instead of covering a whole section. One technique to resolve that problem is flooding, based on the Dijkstra algorithm.

Getting ready

In this case, we will blend the faction capability for tagging a vertex, with the unit's logic for having a drop-off function, into a class called Guild. This is a component to include in the game object; one for each desired guild:

using UnityEngine;
using System;
using System.Collections;

public class Guild : MonoBehaviour
{
    public string guildName;
    public int maxStrength;
    public GameObject baseObject;
    [HideInInspector]
    public int strenghth

    public virtual void Awake()
    {
        strength = maxStrength;
    }
}

It also needs a drop-off function. However, this time we wanted to create an example using Euclidean distance...

Improving influence with convolution filters


Convolution filters are usually applied via image processing software, but we can use the same principles to change a grid's influence given a unit's value and its surroundings. In this recipe, we will explore a couple of algorithms to modify a grid using matrix filters.

Getting ready

It is important to have grasped the concept of influence maps before implementing this recipe, so that you can understand the context in which it is applied.

How to do it…

We will implement the Convolve function:

  1. Declare the Convolve function:

    public static void Convolve(
            float[,] matrix,
            ref float[,] source,
            ref float[,] destination)
    {
        // next steps
    }
  2. Initialize the variables for handling the computations and traversal of arrays:

    int matrixLength = matrix.GetLength(0);
    int size = (int)(matrixLength – 1) / 2;
    int height = source.GetLength(0);
    int width = source.GetLength(1);
    int I, j, k, m;
  3. Create the first loop for iterating over the destination...

Building a fighting circle


This recipe is based on the Kung-Fu Circle algorithm devised for the game, Kingdoms of Amalur: Reckoning. Its purpose is to offer an intelligent way for enemies to approach a given player and set attacks on it. It is very similar to the formation recipe, but it uses a stage manager that handles approach and attack permissions based on enemy weights and attack weights. It is also implemented so that the manager has the capability to handle a list of fighting circles; this is especially aimed at multiplayer games.

Getting ready

Before implementing the fighting circle algorithm, it is important to create some components that accompany the technique. First, the Attack class is a pseudo-abstract class for creating general-purpose attacks for each enemy, and it works as a template for our custom attacks in our game. Second, we need the Enemy class, which is the holder of the enemy's logic and requests. As we will see, the Enemy class holds a list of the different attack...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Unity 5.x Game AI Programming Cookbook
Published in: Mar 2016Publisher: PacktISBN-13: 9781783553570
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
Jorge Palacios

Jorge Palacios is a software and game developer with a BS in computer science and eight years of professional experience. He's been developing games for the last five years in different roles, from tool developer to lead programmer. Mainly focused on artificial intelligence and gameplay programming, he is currently working with Unity and HTML5. He's also a game-programming instructor, speaker, and game-jam organizer.
Read more about Jorge Palacios