Life With and Without State Machines
Many scripts are constructed entirely within their default state. This is often bad design in Second Life. Consider the following script, which implements a simple switch that can be turned on or off.
Listing 4.1: Programming without State Machines
integer value;
default
{
state_entry()
{
value = TRUE;
}
touch_start(integer total_number)
{
if( value==TRUE )
{
llSay(0,"On");
value = FALSE;
}
else
{
llSay(0,"Off");
value = TRUE;
}
}
}
As can be seen, a global variable, named value, is set to either TRUE or FALSE. As the user touches the object, the object will say either “On” or “Off”. As the object is touched these values will alternate. Also, a note on global variables. Global variables are normally considered bad programming practice. However in Second Life, there is really little choice as to whether to use them or not. Because the Linden Scripting Language does not support user defined classes, global variables are the primary way for a script to hold values long-term.
This same functionality could be created using a state machine. The following lines of code do this.
Listing 4.2: Programming without State Machines
default
{
touch_start(integer total_number)
{
llSay(0,"On");
state off;
}
}
state off
{
touch_start(integer total_number)
{
llSay(0,"Off");
state default;
}
}
The above code creates a second state, named off. This gives the above script two states: default and off. Both states contain their own touch_start event. Both states also use the state command to switch to the opposite state when the object is touched. To create an additional state use the state statement followed by the name of the new state. This was done in the above script with the off state.
This script, like all scripts, begins in the default state. To leave the default state and enter another state, use the state statement. For example, the following command will switch to the off state:
state off;
As can be seen in the above script, the state statement is used in the touch_start event to switch to the off state. Likewise, the touch_start in the off state switches the state back to default.
Whenever a state is entered, the state_entry event is called. This allows the script to setup for the new state. The above script does not make use of a state_entry event. However, state_entry events could have been added for both the default and off states. The state_entry event for a default state is often used to setup the script, as can be seen in the following script.
Listing 4.3: Programming without State Machines
default
{
state_entry()
{
llSay(0,
"The script has entered the default state.");
}
touch_start(integer total_number)
{
state mystate;
}
}
state mystate
{
state_entry()
{
llSay(0,
"The script has entered the mystate state.");
}
touch_start(integer total_number)
{
state default;
}
}
The above script will cycle through two states. When each state is entered, the state_entry event will be called. This could be used to setup any script variables needed by the state. In this example, the state_entry event simply displays the name of the state that has been entered.
It is illegal to declare “state level” variables. For example, the following script segment would be illegalMark Biss2007-12-12T00:00:00As per comment in prev chap ? is "illegal" the most accurate term?.
state mystate
{
string stringForMyState;
state_entry()
{
}
touch_start(integer total_number)
{
}
}The above script segment is attempting to declare the variable stringForMyState inside of the state mystate. This is not allowed. Such a variable should be declared at the top of the script. This will cause the variable to be accessible from anywhere in the script. It is not possible to create variables that are only accessible inside a particular state. Variables are either accessible from the entire script, or they are accessible from inside of the function that declared them.
If you are not used to using state engines it may seem unnatural to use them. It is not required that your scripts make use of state engines. As explained earlier in this chapter it is possible to create scripts without making use of state engines. However, the Linden Scripting Language is optimized for state engines. Because of this, state engines should be used when possible.












