Recast/Detour  2.0.2
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Behaviors

Description

Description of the behavior system.

The behaviors are a center part of Recast/Detour, they will allow you to move the agents in a specific way.

Some predefined behaviors are provided, but of course the user has the possibility to create his own.

What does a behavior do?

Basically the goal of a behavior is to compute a new velocity for a given agent. This new velocity will be used to update the position / orientation of the agent.

It is important to make difference between the following two properties of an agent:

When updating the position of an agent, the desired velocity is used to compute the current velocity which is itself used to determine the next position. In other words, the user should not update the current velocity of an agent himself (although it can be done).

Just remember that the current velocity is updated according to the desired velocity.

Different types of behavior

Several interfaces are provided for behavior creation. The user must inherit from one of these.

Normal behavior: dtBehavior

This is the highest interface in the behavior hierarchy. When implementing this interface, the user has to implement the dtBehavior::update() method, which defines how the behavior will affect the data of the given agent.

Steering behavior: dtSteeringBehavior

A steering behavior is a special kind of behavior. A steering behavior works by computing a force that should be applied to the current velocity of an agent in order to get the desired velocity. This is why the user should doesn't need to implement the dtSteeringBehavior::update() method, but instead he needs to define the dtSteeringBehavior::computeForce() method (and maybe the dtSteeringBehavior::applyForce() method as well).

A steering behavior can be parametrized (see below).

Parametrized behavior: dtParametrizedBehavior

Most of the behaviors cannot work on their own, they need parameters. And these parameters can vary from agent to agent (for instance with a following behavior, each agent can follow a different target). In order to allow your behavior to be parametrized, you need to inherit from dtParametrizedBehavior (which implement the dtBehavior interface) and define the dtParametrizedBehavior::doUpdate() method. This will give you access to a set a methods allowing you to store and access your parameters (which can be represented by any data structure) for every agent.

Note
The parameters can also be used to store any data whose lifetime is the same as the behavior's.

Assign a predefined behavior to an agent

Recast/Detour provides you with a set of predefined behaviors:

Most of these behaviors need some parameters (distance, targets, etc.), and those parameters must be related to the agents. For each behavior there is a data structure containing the necessary parameters. This structure is called dtBehaviorNameParams (where BehaviorName must be replaced by the name of the behavior). Once the parameters are defined, you need to associate them with an agent, then the behavior will know what parameters must be used according to the agent it is updating. Here is a sample code:

// Here we create a behavior. 1 is an indication to the behavior,
// it tells that no more than 1 agents should be using this behavior.
// There can be more or less agents using this behavior than the number you gave, it's not critical.
// This number is just an indication for the allocation size for the HashTable handling the parameters.
dtArriveBehavior arrive(1);
// You also need to associate this behavior to the agent
crowd.pushAgentBehavior(&arrive, myAgent.id);
// Now we create the parameters for this behavior. For the Arrive behavior,
// the already existing structure is dtArriveBehaviorParams.
dtArriveBehaviorParams* arriveParams = arrive.getBehaviorParams(myAgent.id);
float dest[] = {12, 0, 12};
// Now, we need to set the parameters.
arriveParams->distance = 1.f; // Minimal distance to keep between the agent and its target
arriveParams->target = dest; // The target to reach

Create your own behaviors

At some point you might want to create your own behaviors. This can easily be done by using the provided interfaces listed above.

Let's take an example. Say we want to create a behavior where an agent would always take the opposite velocity of its target.

First of all, since we are going to need some parameters (for the target), let's create them:

struct MyParams
{
const int targetID;
};

Now we can create our behavior. Since it uses parameters, we need to inherit from dtParametrizedBehavior:

class MyBehavior : public dtParametrizedBehavior<MyParams>
{
public:
explicit MyBehavior(unsigned nbMaxAgent)
: dtParametrizedBehavior<MyParams>(nbMaxAgents)
{}
virtual ~MyBehavior() {}
protected:
virtual void doUpdate(const dtCrowdQuery& query, const dtCrowdAgent& oldAgent, dtCrowdAgent& newAgent,
const MyParams& currentParams, MyParams& newParams, float dt)
{
float* targetVelocity[3];
dtVcopy(targetVelocity, query.getAgent(currentParams.targetID)->vel);
dtVscale(targetVelocity, targetVelocity, -1.f);
dtVset(newAgent.desiredVelocity, targetVelocity);
}
};

Now we have a (simple) behavior ready to be used.

// We create a crowd
dtCrowd crowd;
int nbMaxAgents = 1000;
float maxRadius = 10.f;
crowd.init(nbMaxAgents, maxRadius, navigationMesh);
// Assign agents to the crowd...
// We create the behavior and attach the target to it
MyBehavior b(1);
MyParams* params = b.getBehaviorParams(idAgent);
// We configure the parameters
params->target = crowd.getAgent(idTarget);
// We set the behavior for the agent
crowd.pushAgentBehavior(idAgent, &b);

Now our behavior has been assigned to the agent. The next time the crowd updates its agents, the agent will go in the opposite direction of its target.

Classes

struct  dtAlignmentBehaviorParams
 Parameters for the alignment behavior. More...
 
class  dtAlignmentBehavior
 Defines the alignment behavior. More...
 
class  dtBehavior
 Interface defining a behavior. More...
 
struct  dtCohesionBehaviorParams
 Parameters for the alignment behavior. More...
 
class  dtCohesionBehavior
 Defines the cohesion behavior. More...
 
struct  dtCollisionAvoidanceParams
 Parameters for the collision avoidance behavior. More...
 
class  dtCollisionAvoidance
 Defines a behavior for collision avoidance. More...
 
struct  dtFlockingBehaviorParams
 Parameters for the flocking behavior. More...
 
class  dtFlockingBehavior
 Flocking behavior. More...
 
struct  dtArriveBehaviorParams
 Parameters for the Arrive behavior. More...
 
class  dtArriveBehavior
 Defines the GoTo behavior. More...
 
struct  NoData
 Empty data structure used when no parameters are required. More...
 
class  dtParametrizedBehavior< T >
 A behavior that can be parametrized. More...
 
class  dtPathCorridor
 Represents a dynamic polygon corridor used to plan agent movement. More...
 
struct  dtPathFollowingParams
 Parameters for the path following behavior The parameters will be automatically initialized when used for the first time by the PathFollowing behavior. More...
 
class  dtPathFollowing
 Defines a behavior for pathfollowing. More...
 
class  dtPipelineBehavior
 Behavior having the ability to contain other behaviors. More...
 
struct  dtSeekBehaviorParams
 Parameters for the seek behavior. More...
 
class  dtSeekBehavior
 This class implements the seek behavior. More...
 
struct  dtSeparationBehaviorParams
 Parameters for the separation behavior. More...
 
class  dtSeparationBehavior
 Implementation of the separation behavior. More...
 
class  dtSteeringBehavior< T >
 Interface defining a steering behavior. More...