Join us in Phaze Demesnes or follow us:

This one-script prim animator is is one of the most useful scripts in Second Life. You can now animate any object, with just one script! Setup is very simple. Just drop the script and a blank notecard into the object, click the object, and give your animation a name. Move all the prims around, and click Record. When done, click the Animation Name, and watch it play back every move! This script uses a new and very fast command called 'llSetPrimitiveParamsFast'. This means that dozens of prims can move almost instantly.

Download the scripts now.

Now you can easily make almost anything move with no scripting knowledge needed. I've even included a wandering animal script I used in this little dinosaur freebie.

  • Wings, legs, toes, body parts
  • Animals/pets
  • Morphing vehicles
  • Shape changing doors
  • Weapons with moving parts

Great Features and a great price - Free!

  • Fast drag & drop setup- just put the script into a prim and click
  • Easy menu driven control
  • Works on attachments or stand-alone prim sets
  • Customizable playback behavior with sample add-on scripts
  • Built-in low lag optimization and no-delay animations using the latest LSL commands
  • Scripter friendly API - accepts link messages and chatted commands
  • Animation example scripts
  • Fully scalable/resizable animations, even after you have recorded your creation!
  • No recording limit - use multiple scripts to animate past the LSL 64K limit
  • Records position, rotation, and scale of every child prim
  • Export animation to note cards for permanent storage

Limits: It cannot move/animate avatars that are sitting on a linked prim.

Unlike other $$ prim puppeteers and animators, there is no need to rename any prims, no need to rez and re-rez, no need to depend upon external servers, and no need for more than one script. It's also expandable and can take commands from other scripts. There is no delay between prim movements like older animators. And best of all, it is open source!

Easy menu driven controls:

Menu
Storage: You can save your animations to one or more note cards to save movements permanently, if you need to reset.

Easy to control: I am including example Sensor, Rez, and Wandering Pet scripts to make it easy to add animation triggers.

API support: If you have some scripting knowledge, you can use Linked Messages to can control your animation in any way you want. You can also type commands into main chat or a private chat channel. Scripts can control your animation anywhere on your sim.

Custom name your animations to run different animation sets independently of each-other in the same object.

Simple step by step directions


Make one prim and add this script: Download the scripts

Add a blank notecard called 'Movement'

Add one or more child prims, and link them to the first prim. Make sure the first prim is the last one you click, then press Ctrl-L to link them together. Here is a simple demo:



Click the prim anywhere to get the menu:



The first step is to name your animation. You can store up to six animations in the main menu, and store as many as you can fit into the note card.

Click 'Name' on the Menu. The script will tell you to type the name in on a secret channel. The number changes each time so it will not interfere with other people who may be editing while using the same script. In this example, it suggests channel /656.

Type in a name on the channel it indicates, such as '/656 Test1' The slash and number tells Second Life this is a private conversation with the prim.



The script will tell you to Position all the child prims. Next, select the Menu item 'Record'.

Move the child prim and rotate it, as I have done below, by 45 degrees:




Click Record
Click Pause to add a 1 second delay
Move child back with Ctrl-Z
Click Record

Click the name that you called your animation, and watch it play back!

You can click Notecard to see the saved coordinates. These can be save in the note card for playback. After saving them, reset the script. It will reload all the coordinates and be ready to go again.

Trigger scripts:


The first script is a simple touch and playback script. When touched, it plays back animations named 'stand' and 'sit' in order, then the next time it is clicked, it plays 'sit'.


integer flag;

default
{
    touch_start(integer total_number)
    {
        if (flag++ %2 == 0)
        {
            llMessageLinked(LINK_SET,1,"stand",""); // stand on all 4's
            llMessageLinked(LINK_SET,1,"wag",""); // stand on all 4's
        }
        else
            llMessageLinked(LINK_SET,1,"sit","");   // sit on rear     
    }
}



This next script is a sensor script. If an avatar gets within 5 meters distance, it plays back animation 'sit'. When all avatars have left, it plays a 'stand' animation.

		
// Sensor
integer sitting = FALSE;

default
{
    state_entry()
    {
        llMessageLinked(LINK_SET,1,"stand",""); // stand on all 4's
        llSensorRepeat("","",AGENT,5,PI,5.0);   // look for people within 5 meters every 5 seconds
    }
    
    // found an avatar
    sensor(integer num_detected)
    {     
        if (sitting)
        {
            llMessageLinked(LINK_SET,1,"sit","");   // sit on rear
            sitting = FALSE;
        }
    }
    
    // no one detected?
    no_sensor()
    {
        if (! sitting)
        {
            llMessageLinked(LINK_SET,1,"stand","");     // stand on all 4's
            sitting = TRUE;
        }
    }
}

Animated Pet Script

This animated pet script requires recorded animations for left, stand , right, sit, wag

You need to pre-record 5 animations to use this script:

'right' should put the right legs forward, as when walking, and 'left' should do the opposite.
'sit should be the animal sitting down, or begging.
'stand' should be the position the animal is in when walking, with legs in a standing position.
'wag' is the tail wagging back and forth.




// pet that wanders 


vector start_pos;
integer what;
vector Destination;
float roam_range = 10;
float STRENGTH = 4.0;  // how hard to turn, bigger = ?
float DAMPING = 0.2;    // and how soon
vector direction = <3,0,0>; // push 3 
vector last_pos = <0,0,0>;  // save last position so we can detect when to walk

list buttons = ["Sit","Stand","Wag","Range","Home","Help"];
integer listener;           // handle for menus to use
key Owner;                    // you
integer channel;            // random channel for listener

tMenu()
{
    channel = llCeil(llFrand(10000) + 876);
    listener = llListen(channel,"","","");
    llDialog(Owner,"Choose an item",buttons,channel);
}

// sets up the vehicle as a car
Physics()
{
    llSetBuoyancy(0.0);
    llSetVehicleFlags(-1);
    llSetVehicleType(VEHICLE_TYPE_CAR);
    llRemoveVehicleFlags(VEHICLE_FLAG_LIMIT_MOTOR_UP | VEHICLE_FLAG_LIMIT_ROLL_ONLY);
    llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.8);
    llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.8);
    llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.8);  // hover 
    llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, .1);
    llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1.0, .1, 1000.0>);
    llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <.1, .1, .1>);
    llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, .8);
    llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_BANKING_EFFICIENCY, 0.25);
    llSetVehicleFloatParam(VEHICLE_BANKING_TIMESCALE, 0.1);
    
}

// points the animal in the correct diriction and give it a walk-like push
DoMove()
{
    llStopLookAt();
    llRotLookAt(llRotBetween(<1,0,0>, Destination - llGetPos()), STRENGTH, DAMPING);
    llSleep(DAMPING*3);
    llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, 1 * direction);
    llSleep(0.1);
    llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, ZERO_VECTOR);

}

// get a new destination
next_move()
{
     // random direction
    Destination = llGetPos();
    Destination.x += llFrand(roam_range);
    Destination.y += llFrand(roam_range);
}

DoMenu(string msg)
{
    if (msg == "Sit")
    {
       llMessageLinked(LINK_SET,1,"sit","");
       llListenRemove(listener);
    }
    else if (msg == "Wag")
    {
        llMessageLinked(LINK_SET,1,"wag","");
        llListenRemove(listener);
    }
    else if (msg == "Stand")
    {
        llMessageLinked(LINK_SET,1,"stand","");
        llListenRemove(listener);
    }
    else if (msg == "Range")
    {
        llDialog(Owner,"Range from Home:",["5","10","15","20","25","30","40","50","75"],channel);
    }
    else if (msg == "Home")
    {
        start_pos = llGetPos(); // remember our home
        llListenRemove(listener);
        llOwnerSay("Home is set, wander distance is set to " + (string) roam_range + " meters");
    }
    else if (msg == "Help")
    {
        llLoadURL(Owner,"Click for Help", "/Secondlife/Posts/Prim-Animator");
        llListenRemove(listener);
    }
    else 
    {
        roam_range = (float) msg;
        llOwnerSay("Range set to " + (string) roam_range + " meters");
        llListenRemove(listener);
    }

}



// startup state where we sit, stand and wag tail
default
{
    state_entry()
    {
        Owner = llGetOwner();
        llOwnerSay("Range set to " + (string) roam_range + " meters");
        llOwnerSay("Home set here");
        llOwnerSay("Click me for help");
        start_pos = llGetPos(); // remember our home
        
        state sitting;
    }
}

state sitting
{
    state_entry()
    {
        llSetStatus(STATUS_PHYSICS, FALSE);
        llSetTimerEvent(5);
    }
    
    listen(integer channel,string name, key id, string msg)
    {
        DoMenu(msg);
    }
        
    touch_start(integer n)
    {
       if (llDetectedKey(0) == Owner)
            tMenu();
    }
    
    timer()
    {
       if (what++ %2 == 0)
       {
            llMessageLinked(LINK_SET,1,"stand","");
            llMessageLinked(LINK_SET,1,"wag","");
        }
        else
        {
            llMessageLinked(LINK_SET,1,"sit","");
        }
       
        if (what > 2)
        {
            what = 0;
            state  moving;
        }
    }
    on_rez(integer p)
    {
        llResetScript();
    }
}

// walking around
state moving
{
    state_entry()
    {
        
        Physics();              
        llMessageLinked(LINK_SET,1,"stand",""); // stand on all 4's
        llSetStatus(STATUS_PHYSICS, TRUE);      // get ready to move
        llSetTimerEvent(0.1);
    }
    
    listen(integer channel,string name, key id, string msg)
    {
        DoMenu(msg);
    }
    
    touch_start(integer n)
    {
        if (llDetectedKey(0) == Owner)
            tMenu();
    }

    
    timer()
    {
        DoMove();
        
        if (llVecDist(last_pos, llGetPos()) > .1)
        {
            llMessageLinked(LINK_SET,1,"left",""); // left foot forward
            llMessageLinked(LINK_SET,1,"stand",""); // stand on all 4's
            llMessageLinked(LINK_SET,1,"right",""); // right foot forward
            llMessageLinked(LINK_SET,1,"stand",""); // stand on all 4's
            last_pos = llGetPos();
        }
        if (llVecDist(start_pos,llGetPos()) > roam_range)
            Destination = start_pos;
        
        if (llVecDist(start_pos,llGetPos()) < .5)       // at home
            state sitting;
    
        if (llVecDist(Destination,llGetPos()) < .2)     // at destination
            next_move();
            
       
        
    } 
    
    on_rez(integer p)
    {
        llResetScript();
    }
    
}

Back to the Best Free Tools in Second Life and OpenSim.