State Transition Dialog
Bottom of the Page

Create panel (Helpers) Object Type rollout Crowd Setup rollout (Cognitive Controllers) Cognitive Controller Editor Right-click a transition line.

Select a Crowd object. Modify panel Setup rollout (Cognitive Controllers) Cognitive Controller Editor Right-click a transition line.

These settings control how character studio effects a transition from one state to another when using a cognitive controller. For more detailed information, see To set up and use a cognitive controller.

The Transition Script

The most important element of the transition is the MAXScript conditional script. This is a script associated with the controller that is executed once per frame, and can test any aspect or aspects of the scene and cause a transition or not, depending on whether the result of the test is successful (true, or 1) or unsuccessful (false, or 0).

character studio executes scripts once per frame per assigned delegate, so objects and effects can be animated and still let delegates react with accuracy.

All scripts used in transitions use the following structure:

fn [FunctionName] del t = ( 
[MAXScript code] 
if [MAXScript conditional] 
then 1 
else 0 )

The opening section contains "fn" (function) followed by the function name, which also must appear in the State Transition dialog, and then the input parameters "del t", and lastly "= (". Following this there can be any MAXScript code, or none.

The closing section contains a necessary MAXScript conditional, and then "then 1 else 0". This means: If the result of the conditional is true, then return 1 (that is, the transition is to take place), or if the result of the conditional is false, then return 0 (that is, the transition is not to take place). You could reverse the order of the numbers 1 and 0 ("then 0 else 1") so that the conditional being true would cause no transition to take place, and vice-versa. Lastly, the function must end with a close parenthesis: ")".

Following are some examples of scripts that can be used in cognitive controllers, along with brief explanations. These are presented for you to modify and use in your own scenes.

NoteSee this topic in the online User Reference for sample code to test an object position, test the distance between two objects, and test a modifier parameter.

Testing a Particle System Parameter

This sample script tests the number of particles emitted by particle system Spray01, and returns positive if the number equals 100.

fn TestParticles del t = ( 
if (particleCount $Spray01) == 100 
then 1  else 0 )

Testing an Object Position

This sample script tests the location of the object named Sphere03, and returns positive if its position is (X>=150, Y>=0, Z>=70).

fn PositionCheck del t = ( 
if ($sphere03.pos.x >= 150  and $sphere03.pos.y >=0  and $sphere03.pos.z >=70) 
then 1  else 0 )

Testing an Atmospheric Property

This sample script tests the Density parameter of a fog effect, and returns positive if it equals 50.

fn TestAtmos del t = ( 
atmos_fog = getAtmospheric 1 
print atmos_fog.density -- to:debug 
if (atmos_fog.density == 50) 
then 1 else 0 )

Note the second line, which assigns the fog atmospheric to a variable named "atmos_fog". This is necessary only for atmospheric effects; with most standard objects, you simply use the object name preceded by a $, as in the two previous examples. The "1" following the getAtmospheric command refers to the atmospheric's position in the Rendering Effects dialog Effects list.

Once you've executed this assignment, you can obtain a list of the atmospheric's properties by entering this command in the MAXScript Listener:

ShowProperties atmos_fog

Also, the third line in the sample script isn't necessary for the cognitive controller; it simply prints the result of the test in the Listener window for debugging purposes.

Testing the Distance Between Two Objects

This sample script uses MAXScript's Distance function to obtain the distance between a delegate and a scene object, and returns positive if the result is less than 30.

fn TestDist del t = ( 
get_dist=distance $sphere01.pos $delegate02.simpos 
print (get_dist) 
if get_dist < 30 
then 1 else 0 )

As in the previous example, a variable is used; this time, just to keep the script simple. In the second line, the Distance function is used to obtain the distance between a sphere and a delegate, and the result is assigned to the variable "get_dist". If you wanted to test all delegates that use the cognitive controller instead of a specific one, you'd replace "$delegate02.simpos" with "del.simpos".

NoteThe special property "simpos" is used to determine a delegate position during a simulation solution. This is necessary because newly calculated delegate positions aren't available to MAXScript via the standard "[node].pos" property during a simulation. To get other transformation data calculated during a simulation solution, such as rotation, use the “simTransform” property, which is documented in the MAXScript Help.

In the third line of the script, the calculated distance is printed to the Listener window, for debugging purposes. This line is not necessary for the simulation and can be deleted. Lastly, the value is compared with the constant 30, and if it is less, the script returns a 1, indicating that the transition is to take place.

You can draw on this script to create a cognitive controller that uses multiple Seek behaviors/states to move delegates along a path among any number of objects. As soon as the delegate is within a given distance of a specified object, the transition takes place and the delegate starts using the next Seek state, thus moving toward the next object. Because the transition is tested at each frame, the target objects can be moving in any way you like, resulting in a seemingly dynamic animation.

Testing a Modifier Parameter

This sample script checks the Angle parameter of a Bend modifier applied to a cylinder, and returns true if it is between 70 and -70, inclusive.

fn TestBend del t = ( 
if ($cylinder01.bend.angle <= 70 and $cylinder01.bend.angle >= -70) 
then 1 
else 0 )

Note that the If statement in the second line uses parentheses around the text because the script tests for two conditions: whether the angle is less than or equal to 70, and whether the angle is greater than or equal to -70. Because of the "and" between the two tests, the script returns true only if both are true.

Testing Another Delegate's Behavior

You might want to determine in a transition script which behavior is currently influencing a certain delegate. Crowd provides a MAXScript-based method for doing this. You can even check whether a particular delegate is specified as a target within that behavior. An example would be a cocktail party scene in which Betty avoids Harry if Harry is seeking Sally. But if Harry is avoiding Sally, then Betty will seek Harry.

The following example script is taken from the sample file party.max, which you can find in the Biped download available on this page, under 3ds Max 8 Tutorials – Scene and Support Files Specialized. The scene uses a more complex scenario than the example described in the previous paragraph. Following is an overview, but to fully understand the setup, you should examine the scene. Study, in particular, the behavior assignments and cognitive controllers, which use a total of eight different transition scripts.

Six delegates are confined in a "room" defined by four grids, using a Wall Repel behavior. Delegates 1, 2, 3, and 5 simply wander at random during the simulation. However, delegate 4 uses a cognitive controller (cc1) that tells it to start wandering, and then switch to one of three Avoid behaviors if members of one of three arbitrary pairs of delegates come within 50 units of each other. Each of the Avoid behaviors targets a different group of three delegates, two of which include delegate 2. Delegate 6 is assigned a second cognitive controller (cc2) that uses the following script to tell it to switch to an Avoid behavior if delegate 4 is avoiding delegate 2. The heart of the script is this line in function transfunc4:

(isDelAvoid =  isDelegateAvoiding "$Delegate04" "$Delegate02" 

Load the file, press F11 to open the Listener window, and then solve. The Listener window displays a message whenever delegate 4 is found to be avoiding delegate 2.

You can use this script as is in your own simulations to check for whether one delegate is avoiding a second by substituting the delegates' names in the above line, and also substituting the names of your Avoid behaviors in the list in transfunc4, adding or deleting lines as necessary.

The example script illustrates a second important point: Cognitive controller transition scripts can contain multiple functions. Crowd first executes the function specified in the State Transition dialog Transition Condition field, and that function calls one or more additional functions in the script, which, of course, can also call functions. In this case, transfunc4 calls the first function, isDelegateAvoiding, passing it three parameters.

Lastly, the script contains a special function, getBehaviorType, that compares an input behavior against a list of known behaviors, and on a match, returns the known behavior. In this case, transfunc4 runs through the list of behaviors currently influencing Delegate04, testing each with getBehaviorType, and if an Avoid behavior is in effect, proceeds to check whether Delegate02 is an obstacle of that Avoid behavior. Use of this function is more efficient and flexible than testing for specific behaviors, especially if your scene contains many behaviors of the same type, or you're constantly editing behavior settings. You can see the returned behaviors by removing the comment (double hyphen) from the beginning of the following line in transfunc4.

 -- format "Return Behavior: %\n" return_behavior 
fn isDelegateAvoiding theCurrentBehavior theCogDelegate theAvoidingDelegate = (
 the_return = 0  
 counter = 1
 for the_assignments in $Crowd01.assignments do 
 if the_return == 1 then exit
 if the_assignments.delegate != undefined then 
 if theCogDelegate == "$" then 
 if the_assignments.cogcontrol != undefined then 
 for the_cogcontrol_state in the_assignments.cogcontrol.states do
 if the_return == 1 then exit
 for the_cogcontrol_state_behavior in the_cogcontrol_state.behaviors do 
 if the_return == 1 then exit
 if == theCurrentBehavior then
 for the_obstacle in the_cogcontrol_state_behavior.obstacles do
 if the_return == 1 then exit 
 if "$" == theAvoidingDelegate then 
 --format "Set it true here !\n" 
 the_return = 1
 counter = counter + 1 
fn getBehaviorType val = 
( if not iskindof val MAXRefTarg do return undefined 
 theBehaviors = #( Speed_Vary_Behavior ,Orientation_Behavior ,Scripted_Behavior ,
 Wander_Behavior ,Surface_Arrive_Behavior ,Path_Follow_Behavior ,
 Seek_Behavior ,Avoid_Behavior ,Wall_Seek_Behavior ,
 Space_Warp_Behavior,Wall_Repel_Behavior,Surface_Follow_Behavior ,
 Repel_Behavior )
 val_classID = val.classid
 for behav in theBehaviors do 
 ( local behav_classid = behav.classid 
 if val_classID[1] == behav_classid[1] and val_classID[2] == behav_classid[2] do 
 return behav 
fn transFunc4 del t = (
another_the_return = 0 
counter = 1 
for the_current_behavior in $Delegate04.behaviors do 
 if another_the_return == 1 then exit 
 return_behavior = getBehaviorType the_current_behavior
 --format "Return Behavior: %\n" return_behavior
 if return_behavior == Avoid_Behavior  then 
 isDelAvoid =  isDelegateAvoiding "$Delegate04" "$Delegate02" 
 if isDelAvoid == 1 then 
 format "$Delegate04 found to be Avoiding $Delegate02\n"
 format "              Starting Transition in frame %:\n" t
 another_the_return = 1
 counter = counter + 1 



Sets the transition's precedence.

When more than one transition tests true, character studio uses the Priority setting to determine which transition occurs. It performs the transition with the lowest Priority setting. Thus, for example, a transition with a Priority setting of 0 takes precedence over one with Priority 1, and so on.


The number of frames character studio takes to effect the transition between states.

Ease In

The rate at which the transition begins. Default=0.5. Range=0 to 1.0.

Lower values cause a more abrupt transition, while higher values cause a more gradual transition.

Ease Out

The rate at which the transition ends. Default=0.5. Range=0 to 1.0.

Lower values cause a more abrupt transition, while higher values cause a more gradual transition.

NoteThe sum of the values for Ease In and Ease Out must be less than or equal to 1.0. character studio won't let you set a value for either parameter that would cause the sum to exceed 1.0. To increase the value of one parameter when its value equals 1.0 minus the other parameter, decrease the other parameter first.
Transition Condition

The name of the MAXScript function that specifies when/how the transition is to occur.

This name must also appear at the beginning of the main function in the script, after "fn". The script can contain additional functions that are called by the main function and each other.

Edit MAXScript

Opens an editor window for editing, saving, and loading the transition's MAXScript script.



Closes the dialog and implements changes.


Closes the dialog and ignores changes.