Samstag, 10. Dezember 2011

llSetKeyframedMotion: Neue LSL-Funktion mit vielen Möglichkeiten

Am 15. November wurde die neue LSL-Funktion llSetKeyframedMotion im gesamten Main Grid von Second Life eingeführt. Dieser Skriptaufruf ermöglicht es, in einer einzigen Skriptzeile ein Objekt so zu bewegen, dass es mehrere Richtungsänderungen durchführt. Aber auch einfache Punkt-zu-Punkt Bewegungen sind damit leicht machbar. Die Bewegungen werden dabei sehr weich berechnet, ganz im Gegensatz zum alten llSetPos und llSetRot.

Als Option können dem llSetKeyframedMotion-Aufruf noch einige Steuerbefehle angehängt werden, wie etwa das Ausführen als Schleife (KFM_LOOP), der Vor- und Zurück-Modus (KFM_PING_PONG), oder in umgekehrter Abfolge (KFM_REVERSE). Die Wegstrecken innerhalb des gleichen Aufrufs, sind auch über Regionsgrenzen hinweg möglich. Das ist zum Beispiel wichtig für Tour-Vehikel, die mehrere Regionen in ihrer Route haben.

Da das hier doch etwas länger wird, geht es weiter nach dem Link:


Ein paar Einschränkungen gibt es auch:
  • Zur Zeit kann llSetKeyframedMotion nur bei nicht-physischen Objekten angewendet werden.
  • Die Funktion kann nur in einem Skript im Rootprim eines Linksets aufgerufen werden.
  • Das Rootprim des Linksets muss im Baufenster unter "Eigenschaften" auf "Konvexe Hülle" gesetzt werden. Das geht nur mit einem Mesh-Viewer. Für nicht meshfähige Viewer gibt es eine Alternative innerhalb des Skripts, auf die ich hier nicht eingehe.
  • Das Prim-Equivalent für Physik darf für das bewegte Objekt maximal 64 betragen.
  • Wird das animierte Objekt vom Eigentümer oder von einem Passagier mit "Bearbeiten" ausgewählt, stoppt die Animation und beginnt nach Verlassen des Bearbeiten-Modus von vorne.
  • Beim Laufen auf einer sich bewegenden Plattform, kann es zu merkwürdigen Verrenkungen des Avatars kommen.
  • Mit Einstellung "Konvexe Hülle" und dem im Prim enthaltenen Skript, ist der Land Impact (Primverbrauch) wesentlich höher, als die tatsächlich verbauten Prims.

Da das Rootprim für die Funktion auf Konvexe Hülle gesetzt werden muss, hat man einen sehr feinen Nebeneffekt. Das Prim verhält sich gegenüber dem Avatar, als wäre es physisch. Somit wird der Avatar, der sich auf diesem Prim befindet, automatisch mitbewegt. Ein "Setzen" über llSitTarget, oder ein Poseball, ist nicht notwendig. Einfach draufstellen und mitnehmen lassen. Dabei darauf achten, nur das Rootprim auf konvexe Hülle zu stellen und nicht das ganze Linkset, da sonst, wie bei einem Sculpty, eine unsichtbare Bounding-Box ein Betreten verhindert.

Die Funktionsweise der Animation/Bewegung ist relativ. Das bedeutet, es wird für jeden neuen Streckenpunkt nur die Änderung zum vorherigen Streckenpunkt angegeben. Da die Bewegung in Form von Frames berechnet wird und nicht in Echtzeit, entstehen leichte Differenzen zwischen vorgegebener und tatsächlich ausgeführter Bewegung. Um diese Abweichungen möglichst gering zu halten, sollte die angegebene Zeit zwischen zwei Streckenpunkten ein Vielfaches von 1/45 betragen (z.B. 90.0/45.0). Dies ist bedingt durch die Sim-Performance, die im Idealfall 45 FPS haben sollte.

Mögliche Einsatzgebiete für llSetKeyframedMotion sind:
  • Aufzüge
  • Bewegliche Plattformen
  • Eisenbahn, bzw. Vehikel mit fest vorgegebener Streckenführung
  • Türen, Schranken, Zugbrücken, etc.
  • Windmühlen, Maschinen

Zum Abschluss der Einleitung noch die Erklärung der Funktion:

Aufruf:
llSetKeyframedMotion( list keyframes, list options );

list keyframes:
  • einzelne (oder mehrere) Vektor-Position(en)
  • einzelne (oder mehrere) Rotationsanweisung(en), auch in Kombination mit Vektor-Position(en)
  • Ablaufzeit

list options:
  • KFM_MODE gefolgt von einer dieser Anweisungen:
    • KFM_LOOP - die Bewegung wird endlos wiederholt
    • KFM_REVERSE - die Bewegung läuft spiegelverkehrt ab
    • KFM_FORWARD - die Bewegung läuft linear ab
    • KFM_PING_PONG - die Bewegung wird vor und zurück ausgeführt
  • KFM_DATA gefolgt von einer dieser Anweisungen:
    • KFM_TRANSLATION - Bewegung zu neuem Vektorpunkt
    • KFM_ROTATION - Rotation des Objektes um seinen eigenen Mittelpunkt
      • Hat man Bewegung und Rotation im selben Aufruf, dann beide Anweisungen aufführen
      • Nutzt man nur Bewegung oder Rotation, dann auch nur die entsprechende Option aufführen
  • KFM_COMMAND gefolgt von einer dieser Anweisungen:
    • KFM_CMD_STOP - beendet die Bewegung und setzt sie an den Anfang zurück
    • KFM_CMD_PAUSE - hält die Bewegung an
    • KFM_CMD_PLAY - setzt die mit Stop oder Pause angehaltene Bewegung fort
      • KFM_COMMAND kann nur alleinstehend aufgerufen werden und darf nicht im selben Aufruf stehen, in der eine Keyframe-Bewegung definiert ist

So, viel Text im Vorfeld. Nun ein Beispiel zum Nachvollziehen. Als Grundlage habe ich ein ganz einfaches Skript mit Dialog-Menü erstellt, bei dem man auswählen kann, welche Bewegung ausgeführt werden soll.

Dazu habe ich mir diesen Versuchsaufbau gebastelt:


Das ockerfarbene Ding in der Mitte ist meine Plattform, die sich bewegen soll. Das Skript ist genau für die Abstände ausgelegt, die angegeben sind. Die globale X-Achse verläuft von links nach rechts durch das Gebäude.

Und so sieht die Plattform aus, in deren Rootprim sich das Skript befinden muss:


Damit das Skript funktioniert, muss das Rootprim auf "Konvexe Hülle" gestellt werden. Dazu im Baufenster die Checkbox vor "Verknüpfte Teile bearbeiten" aktivieren, das Rootprim auswählen und unter "Eigenschaften" die "Art der physischen Form" auf "Konvexe Hülle" setzen.



Hier ist das Skript. Beim Kopieren die Linien oben und unten nicht mit auswählen:

===============================================================================

integer channel = 333;

default
{
    state_entry()
    {
        llListen(channel,"", "","");
    }

    touch_start(integer total_number)
    {
        llDialog(llDetectedKey(0), "Bitte Richtung für die Plattform wählen:",
                            ["Runter 5m", "Rechts 5m", "Runter 10m", "Hoch 5m",
                             "Links 5m", "Hoch 10m", "Verlassen"], channel);
    }
    listen(integer chan, string name, key id, string mes)
    {
        if (mes == "Hoch 5m")
            llSetKeyframedMotion([<0,0,5.0>, 5], [KFM_DATA, KFM_TRANSLATION,
                                                    KFM_MODE, KFM_FORWARD]);
        if (mes == "Runter 5m")
            llSetKeyframedMotion([<0,0,-5.0>, 5], [KFM_DATA, KFM_TRANSLATION,
                                                    KFM_MODE, KFM_FORWARD]);
        if (mes == "Hoch 10m")
            llSetKeyframedMotion([<0,0,10.0>, 10], [KFM_DATA, KFM_TRANSLATION,
                                                    KFM_MODE, KFM_FORWARD]);
        if (mes == "Runter 10m")
            llSetKeyframedMotion([<0,0,-10.0>, 10], [KFM_DATA, KFM_TRANSLATION,
                                                    KFM_MODE, KFM_FORWARD]);
        if (mes == "Links 5m")
            llSetKeyframedMotion([<5.0,0,0>,
                                    llEuler2Rot(<0, 0, 90> * DEG_TO_RAD), 5],
                                    [KFM_MODE, KFM_REVERSE]);
        if (mes == "Rechts 5m")
            llSetKeyframedMotion([<5.0,0,0>,
                                    llEuler2Rot(<0, 0, 90> * DEG_TO_RAD), 5],
                                    [KFM_MODE, KFM_FORWARD]);
        if (mes == "Verlassen")
            llResetScript();
    }    
}
===============================================================================

Den Skripttext einfach in ein neu erzeugtes Skript im Rootprim der Plattform einfügen. Die Checkbox für Mono kann man vor dem Speichern ausschalten, da es keinen Vorteil bringt.

Klickt man nun irgendein Prim der Plattform an, öffnet sich dieses Menü:

Skriptmenü
Mit Hoch oder Runter 5m erreicht man die Zwischenebene in meinem Versuchsaufbau.

Mit Links oder Rechts 5m bewegt sich die Plattform horizontal in eine, der beiden Mulden der Zwischenebenen. Dabei wird eine 90° Drehung ausgeführt, damit die offene Seite des Geländers zur Zwischenebene zeigt.

Mit Hoch oder Runter 10m kann man sich zwischen den Hauptebenen bewegen.

Hier nochmal alle Möglichkeiten im Überblick:


Dies ist, wie schon erwähnt, nur ein ganz einfaches Beispiel, was auch anhand des kurzen Skripts ersichtlich ist. Mit etwas Aufwand und Nutzung aller Möglichkeiten, lassen sich mit llSetKeyframedAnimation richtig gute Dinge umsetzen. Einziger Nachteil: Durch Umstellen auf "Konvexe Hülle", hat die Plattform mit nur 4 echten Prims, eine Auswirkung auf das Land von 24 Prims (Land Impact). Und das, obwohl hier noch nicht mal Mesh im Spiel ist.

Ich hoffe, ich konnte den einen oder anderen zu eigenen Experimenten mit dieser neuen Funktion anregen.

Quelle: Second Life Wiki - llSetKeyframedMotion

1 Kommentar:

  1. Wenn auch ein etwas älterer Artikel, aber sehr gut beschrieben.
    Genau das wonach ich eben gesucht habe.
    Vielen Dank dafür :)
    Trawell

    AntwortenLöschen