MAXScript Extensions > MAXScript Extensions for character studio > Crowd MAXScript Extensions > Crowd Behaviors >

# Scripted_Behavior : MAXObject

    Scripted_Behavior - superclass: ReferenceTarget; super-superclass:MAXWrapper - 4:0 - classID: #(716798510, 1784546452)

| Character Studio - Quick Navigation

Introduction to the Crowd System

The crowd system works by assembling all of the force vectors and speeds for a delegate from its active force behaviors. Then based upon the delegate’s motion parameters, these force vectors and speeds are averaged and integrated to create a velocity for the delegate. This velocity may then be modified if the delegate has an active constraint behavior or if it has an active default Avoidance behavior.

After the velocity is set, if there is an active orientation behavior, it is used to set the orientation of the delegate, otherwise the orientation is calculated from the default delegate parameters. Finally, the velocity is integrated and a new position is calculated.

The new position of the delegate isn't set until after all of the forces are calculated for all of the behaviors.

For a biped crowd, bipeds work off of goals and not forces when determining which direction they should go in. So, in order to create a force behavior that will work with a Biped, a goal position must be specified. No forces need to be integrated into velocities because the movement of the Biped isn’t based upon calculating velocities but rather by selecting clips found in the motion flow graph.

Constructor

    Scripted_Behavior ... ScriptedBehavior ...

Properties

    <scripted_behavior>.name String Default: "Scripted"

    <Scripted_Behavior>.scriptContextName String Default: "apply" Alias: Script_Context_Name

The script functions declared in the Edit MaxScript window are declared in a hidden MaxScript context. This textbox specifies the name of the context. Giving a unique name here avoids conflicts between different scripted behaviors.

    <Scripted_Behavior>.type Integer Default: 0 Alias: Behavior_Type

One of three behavior types: Force, Constraint, or Orientation.

Force: Behaviors of this type force the delegates to move in a particular direction, for example, Seek and Repel. Force behaviors work by returning a force vector in the direction that the behavior want’s the delegate to go in, and in some cases the speed it should be traveling at and the goal at which it is trying to reach.

Constraint: Behaviors of this type restrict the position and velocity of a delegate, for example, SurfaceFollow. Constraint behaviors set the velocity and sometimes may even change the delegate’s position, in order to meet the constraint. You may only have one active constraint behavior per delegate per frame.

Orientation: Behaviors of this type affect only the orientation of the delegates, for example Orientation. These behaviors don’t work with forces but instead return an orientation that the delegate should be at, represented by a quaternion. Any active orientation behavior will override the default orientation of the delegate. The velocity determines the default orientation. Like a constraint behavior, you may only have one active orientation behavior per delegate per frame.

Note

Though there are no avoid behavior types, a force or constraint behavior may be used to create an avoidance behavior.

We do recommend though that the default Avoidance behavior be used due to the fact that it is well integrated into the crowd solution pipeline.

    <scripted_behavior>.script: string

## Edit MaxScript

This button "Edit MaxScript", in the Scripted Behavior Rollout, opens a MAXScript editor window that can be used to enter a scripted behavior script. The editor window is similar to other MaxScript editor window but is slightly customized for scripted behaviors.

The following elements in the File Menu work differently

New: disabled since only one editor per scripted behavior can be open at any time

Open: opens a file in the existing editor window. Any existing text will be lost.

Evaluate: evaluates the script and saves it into the behavior's paramblock

Close: saves into the behavior's paramblock and closes the editor if no errors found

## Scripted Behavior Syntax

The scripted behavior script is implemented by defining a set of event handlers that get called by the crowd system when solving the simulation. The event handlers are automatically enclosed into a hidden MAXScript context. The name of the context is taken from the dialog’s Script Context Name text box or its equivalent . scriptContextName.

## Event Handlers for Scripted Behaviors

    on execute do <expr>

Called whenever the script is evaluated. All initializing should be done here.

    on setupDelegates <delegates> <behavior>do<expr>

<delegates> an array of all the delegates after they are ordered participating in the simulation. All delegates listed in the Behavior Assignments pane of the Behavior and Team Assignment dialog are found in this list.

<behavior> the current behavior

Called before the simulation starts.

NoteAll of the delegates are passed in, regardless if they have this behavior assigned, so the behavior knows the max number of delegates that may be used and therefore set up whatever data structures required. Some behaviors need to keep track of parameters on a per delegate basis. This function allows the behavior to set up data structures to get that info. Also that is one of the reasons why the delegate.id is unique, so it can be used to hash or index these data structures. Due to cognitive controllers, you never really know exactly all of the delegates which will be active for a particular behavior.

    on display <behavior> <time>do<expr>

<behavior>the current behavior

<time>current time of the simulation

Called every time the crowd system is redrawn. You can use the low level drawing functions from the gw struct,Viewport Drawing Methods, to have a custom display for the behaviors.

Note

This handler gets called a number of times, so the system will slow down if implemented.

    on behaviorStarted <delegate> <behavior> <time>do<expr>

<delegate>the delegate node the behavior is assigned to

<behavior>the current behavior

<time>current time of the simulation

Called whenever a behavior becomes active for a particular delegate. This can occur at the beginning of the simulation for an assigned behavior or when a cognitive controller activates the behavior.

    on initAtThisTime <behavior> <time>

This function is called for each behavior at the beginning of the frame.

    on applyForce <delegate> <behavior> <time> <numSubSamples> <displayHelpers> <weight>do<expr>

If the behavior type is Force or Orientation, this handler is called every frame to move the delegate.

<delegate> the delegate node the behavior is assigned to

<behavior> the current behavior

<time> current time of the simulation

<numSubSamples> is the number of sub samples required per frame.

<displayHelpers> this value is true/false depending on the <Crowd>.update and <Crowd>.updateFrequency , as well as the current frame. If it is true, you should display any helper imagery you want using the display functions available from the delegates structure. For instance, most behaviors display their force if this is true, and pathfollow also displays its target. The delegates.lineDisplay,.sphereDisplay, .bboxDisplay, and .textDisplay are all functions which can be used to draw a graphic primitive for a particular delegate when the crowd simulation is being solved. Please see Viewport Drawing Methods for additional viewport drawing methods.

Note

The graphic window functions gw.* described in Viewport Drawing Methods will not display correctly or at all while in Step Solve.

<weight> this behavior’s weight on the delegate

The event handler should return an array of the following type:

    #(<int_flags>, <point3_force>, <point3_goal>, <float_speed>, <Speed_Weight_at_the_Goal>)

<int_flags> sum of any of the following values:

0 - the return value is not used by the crowd system

1 - only forceis affected

2 - only goalis affected

4 - only speedis affected

For example, a value of 5, (1+4), indicates that the force and speed are affected.

<point3_force> the force vector. It should be unit normalized and then multiplied by the delegate’s average speed. Modify this value, greater or less, to make the force stronger or weaker.

<point3_goal> the goal position in world space.

<float_speed> the net speed of the delegate. This value should be normalized to the average speed of the delegate. A value of 1.0 means go at the average speed.

<Speed_Weight_at_the_Goal> will represent the speed that the delegate should be at when it reaches its goal. This value should be normalized by the average speed of the delegate, so that a value of 1.0 equal it's average speed.

NoteAny behavior that sets the <int_flags> with a speed affected setting should ensure that a valid value is set for <float_speed> and <Speed_Weight_at_the_Goal>. Note that a goal doesn't need to be set for this to work. This is how the 'SpeedVary' behavior works with Biped. It doesn't explicitly set a goal but still modifies the <Speed_Weight_at_the_Goal> value.

    on constraint <delegate> <behavior> <time> <numSubSamples> <displayHelpers> <finalSet> <velocity> <speed> <pos>do<expr>

If the behavior type, <Scripted_Behavior>. type, is Constraint, this handler is called at least once every frame to constrain the delegate. The constraint behavior will override any other force behavior, the Avoidance Behavior, plus it will override any acceleration limits, speed limits etc. So it should be used with caution in a simulation.

The constraint behavior constrains the position that the delegate is moving towards by changing the current position that the delegate is already at, it's current velocity, and it's current speed. These values are combined to get the next position, Next_position = Current_Position +Normalized(vel) * Speed. Changing the current position doesn't actually change where it is at though, it just changes the position that is used to calculate it's new position. This design allows the constraint to make the objects velocity change abruptly and keep its speed, thus conserving the energy of the delegate.

<delegate> the delegate node the behavior is assigned to

<behavior> the current behavior

<time> current time of the simulation

<numSubSamples> is the number of sub samples required per frame.

<displayHelpers> this value is true/false depending on the <Crowd>.update and <Crowd>.updateFrequency, as well as the current frame. If it is true, you should display any helper imagery you want using the display functions available from the delegate. For instance, most behaviors display their force if this is true, and pathfollow also displays its target. The delegates.lineDisplay, .sphereDisplay, .bboxDisplay, and .textDisplay are all functions which can be used to draw a graphic primitive for a particular delegate when the crowd simulation is being solved. Please see Viewport Drawing Methods for additional viewport drawing methods.

<finalSet> whether or not this is the final time this behavior will be called during the current frame.

NoteIn order to handle constraints working correctly within the avoidance system the constraint behavior may be called more than once per frame. When the passed in parameter,finalSet, istrue,it will be the last time the constraint function is called for that frame.

Currently the constraint behavior's "on constraint" event handler is called twice per frame. The first call occurs before an existing Avoid_Behavior with the passed in parameter finalSet having a value of false . The second call occurs, after the delegate’s limits and Avoid_Behavior are applied with the passed in parameter finalSet having a value of true. This evaluation order is done so that the delegate’s limits and the Avoid_Behavior can affect the changes that the constraint performs. The second call is made to make sure that the constraint is still being met.

One reason to check the state of finalSet is if internally something was cached and you didn't want it to change. For example, the Surface_Followconstraint behavior keeps track of which triangle it's on and the barycentric coordinates of where it's at. The simulation will not change these values until finalSet is true.

<velocity> the current velocity of the delegate at this frame.

<speed> the current speed of the delegate at this frame.

<pos> the current position of the delegate at this frame.

After the last delegate's "on constraint" has executed for the last frame of the simulation, "on setupDelegates delegates behavior do" will be called with an empty array "#() ReferenceTarget:Scripted_Behavior". This is guarenteed and can be used by written constraint behaviors to clear out any internal caches.

The event handler should return an array of the following type:

    #(<int_flags>, <point3_velocity>, <point3_pos>, <point3_goal>, <float_speed>)

<int_flags> sum of any of the following values:

0 - the return value is not used by the crowd system

1 - the return value is used by the crowd system

<point3_velocity> the velocity.

<point3_pos> the modified current position that is used to calculate it's new position. In order to meet a constraint this behavior is allowed to modify the current position of a delegate.

<point3_goal> the goal position in world space.

<float_speed> the net speed of the delegate. This value should be normalized to the average speed of the delegate.

    on orient <delegate> <behavior> <time> <velocity> do <expr>

If the behavior type, <Scripted_Behavior>. type, is Orientation, this handler is called every frame. This handler is always called in conjunction with the applyForce handler.

<delegate> the delegate node the behavior is assigned to

<behavior > the current behavior

<time> current time of the simulation

<velocity> the current velocity of the delegate at this frame.

The event handler should return an array of the following type:

     #(<int_flags>, quat_orientation)

<int_flags> sum of any of the following values:

0 - the return value is not used by the crowd system

1 - the return value is used by the crowd system

<quat_orientation> the orientation of the delegate in quaternions.

Note

The purpose of passing the crowd delegate and behavior to all of the event handlers is that you can call persisted global, saved with scene, MAXScript functions that work for more than one crowd simulation.

EXAMPLE
The following is a pair of scripted behaviors called "FormationConstraint" and "FormationOrientation".
The "FormationOrientation" will constrain the orientation to a fixed location, in this case based on the current delegate's orientation found at its first rotation keyframe. The entire scripted orientation behavior can be implemented with one event handler:
    on orient delegate behavior time vel do
    (
    #(1,delegate.rotation.keys[1].value as quat )
    )
The "FormationConstraint" keeps a team of delegates in a given positional formation while maintaining the pace and direction of a designated leader named "FormationLeader". This is similar to a drum major and a marching band or like football blockers running in front of a running back who may dart in any direction. This person dictates how and where the formation will move. This "FormationLeader" is not using the scripted behavior.
This behavior will affect both the position and orientation of the delegate. The orientation is being calculated by the delegate’s velocity, and the velocity is being set correctly.
    on executedo( print" executed")

    on constraint delegate behavior time numsubsamples displayHelpers finalSet vel speed pos do
    (
    leader_velocity = delegates.velocity $TheFormationLeader
    Normalized_Leader_Velocity= normalize (delegates.velocity $TheFormationLeader)
    magVel = speed*Normalized_Leader_Velocity
    temp_dis = (pos+leader_velocity)- magVel
    the_goal =temp_dis + magVel
    if displayHelpers== true then
    (
    delegates.textDisplay delegate the_goal delegate.wirecolor delegate.name
    delegates.lineDisplay delegate pos (pos+leader_velocity) delegate.wirecolor true
    delegates.sphereDisplay delegate (pos+ (leader_velocity * $Crowd01.vectorScale)) 4
    delegate.wirecolor
    )
    #(1, Normalized_Leader_Velocity, temp_dis, the_goal, speed)
    )

#### See Also

- Delegate:Helper

- Crowd : Helper

- MAXWrapper Common Properties, Operators, and Methods

- Value Common Properties, Operators, and Methods

- MAXScript Extensions in character studio