skimi3d Grid Log in Visit the grid
All scripts
Make things move

Spin It

Makes a prim turn endlessly, and costs the region nothing while it does. The windmill, the fan, the shop sign, the planet.

Goes inThe prim that should turn
Setupone line to change
Code138 lines
Open toOpen to everyone

What it does

It tells every viewer nearby to draw this prim spinning, and then it stops working. The turning happens on the machines of the people watching, not on the region, so the sim sends one short message and goes back to sleep. A hundred of these cost a region less than a single script nudging one prim around with llSetRot. Turns per minute is the setting, because that is the number you can picture; the conversion into what the function actually wants happens once, inside.

What you can build with it

Windmills, ceiling fans, propellers, hanging shop signs, planets and moons, a rotating display in a shop window, a radar dish, a barber's pole. Anything that should look alive without asking the region for anything. Set TOUCH_TO_TOGGLE and it becomes a fan somebody can switch off.

How to use it

1 Drop the script into the prim you want turning.
2 If it turns around the wrong axis, change AXIS. Upright is a carousel; on its side is a wheel or a windmill.
3 Set RPM. 6.0 is one slow turn every ten seconds, 60.0 is one turn a second, and a minus sign turns it the other way.
4 Touch it to stop and start it. Set TOUCH_TO_TOGGLE to FALSE for something that should just turn and be left alone.

Settings you can change

5

Edit these at the top of the script. Everything works on the defaults · change them only when you need to.

AXIS The axis it turns around, in the prim's own body. Upright for a carousel or a radar dish, on its side for a wheel or a windmill. <0.0, 0.0, 1.0>
RPM Turns per minute. 6.0 is one slow turn every ten seconds, 60.0 is one turn a second. A negative number turns it the other way. 6.0
START_SPINNING Whether it should already be turning the moment it is rezzed. TRUE
TOUCH_TO_TOGGLE Touch to stop it, touch again to start it. Set to FALSE for something that should just turn and never be interfered with. TRUE
WHO_MAY_TOUCH 0 for everyone, 1 for the owner alone, 2 for anyone wearing the same group tag. 0
The code LSL · 138 lines · updated 8 Sep 2026 Download .lsl
// =====================================================================
//  Spin It
//  skimi3d script library · https://grid.skimi3d.com/scripts/spin-it
//
//  Makes a prim turn, endlessly, for free.
//
//  This is the cheapest moving thing you can put in a region, and it is
//  worth understanding why. llTargetOmega does not turn the object at
//  all. It tells every viewer nearby "draw this one spinning", and the
//  viewers do the work on their own machines. The region sends one
//  message and then goes back to sleep. A hundred of these cost a
//  region less than one script nudging a prim round with llSetRot.
//
//  The price of that bargain is written at the bottom of this file and
//  in "What it will not do" on the library page. Read it before you use
//  this for anything that has to actually move something.
// =====================================================================


// ---------------------------------------------------------------------
//  Settings
// ---------------------------------------------------------------------

// The axis it turns around, in the prim's own body.
//   <0.0, 0.0, 1.0>  upright, like a carousel or a radar dish
//   <0.0, 1.0, 0.0>  on its side, like a wheel or a windmill
//   <1.0, 0.0, 0.0>  the other way on its side
vector AXIS = <0.0, 0.0, 1.0>;

// Turns per minute. 6.0 is one slow turn every ten seconds, which suits
// a windmill; 60.0 is one turn a second, which suits a fan. A negative
// number turns it the other way.
float RPM = 6.0;

// Should it be turning as soon as it is rezzed?
integer START_SPINNING = TRUE;

// Touch to stop it, touch again to start it. Set to FALSE for something
// that should just turn and be left alone, like a planet or a sign.
integer TOUCH_TO_TOGGLE = TRUE;

// Who may touch it. 0 = everyone, 1 = only the owner, 2 = only people
// wearing the same group tag.
integer WHO_MAY_TOUCH = 0;


// ---------------------------------------------------------------------
//  Everything below here is the machinery
// ---------------------------------------------------------------------

integer gSpinning = FALSE;


spin(integer on)
{
    if (on)
    {
        // llTargetOmega counts in radians a second, which nobody thinks
        // in. Turns per minute is the number you can picture, so the
        // setting is in those and the conversion lives here, once.
        float rate = RPM * TWO_PI / 60.0;
        llTargetOmega(llVecNorm(AXIS), rate, 1.0);
    }
    else
    {
        // A zero axis is how you stop it. Setting the rate to zero on
        // its own leaves some viewers still drawing the last spin.
        llTargetOmega(ZERO_VECTOR, 0.0, 0.0);
    }

    gSpinning = on;
}


integer mayTouch(key who)
{
    if (WHO_MAY_TOUCH == 1) return who == llGetOwner();
    if (WHO_MAY_TOUCH == 2) return llSameGroup(who);
    return TRUE;
}


default
{
    state_entry()
    {
        spin(START_SPINNING);
    }

    touch_start(integer total)
    {
        if (!TOUCH_TO_TOGGLE) return;

        key who = llDetectedKey(0);
        if (!mayTouch(who))
        {
            llRegionSayTo(who, 0, "This one is not yours to stop.");
            return;
        }

        spin(!gSpinning);
    }

    on_rez(integer start)
    {
        // The spin is a property of the prim, not of the script, and a
        // rezzed copy can arrive already turning from whatever state it
        // was taken in. Say it again so rezzed and edited copies agree.
        spin(START_SPINNING);
    }

    changed(integer what)
    {
        // A copy inherits the old spin. Re-stating it after a change of
        // owner or inventory keeps a boxed and re-rezzed one honest.
        if (what & (CHANGED_OWNER | CHANGED_INVENTORY)) spin(gSpinning);
    }
}


// ---------------------------------------------------------------------
//  The catch, in full
//
//  The object does not turn. The viewers draw it turning.
//
//  That means llGetRot never changes, however long it has been going.
//  Nothing mounted on it turns with it. It will not push anything, will
//  not sweep anyone off a platform, and a sensor or a camera sitting on
//  it keeps looking the same way for ever. Two viewers standing side by
//  side may show it at different angles, because each one started
//  drawing at its own moment.
//
//  For a windmill, a fan, a sign, a planet, a shop display, none of that
//  matters and you get the motion for nothing. For a turnstile, a
//  carousel with people on it, or a hand of a clock you want to read,
//  every word of it matters and you need a script that really moves the
//  prim. Move Along Points in this library is the one to start from.
// ---------------------------------------------------------------------

Copy it, make a new script inworld, paste over what is there and save. Nothing here phones home.