Was macht R15)?
Du erstellst eine Bewegung als kleines JSON Bewegungsspezifikation (motion spec): eine Handvoll Schlüsselposen, die in anatomischen Begriffen formuliert sind („rechter Oberarm 90° nach vorne“, „Knie 60° gebeugt“). Die integrierte Engine erledigt alles, was von Hand fehleranfällig ist: Roblox-Gelenkmathematik für beide Rigs, Interpolation, Bodenhaftung der Füße, eine 3D-Vorschau, Plausibilitätswarnungen und den Export gebackener Keyframes.
Der Benutzer beurteilt das Ergebnis, indem er es ansieht, daher lautet die Schleife: Phasen planen → Spezifikation schreiben → bauen → selbst das Storyboard ansehen → korrigieren → Vorschau + Keyframes liefern. Überspringe den Schritt des Ansehens nicht; Posenummern, die auf dem Papier richtig erscheinen, sind oft sichtbar falsch (ein Arm durch die Brust, ein Tritt, der nie den Ball erreicht).
Arbeitsablauf
- Bewegung festlegen. Rig (R6 oder R15; frage nur, wenn es wirklich nicht abgeleitet werden kann, sonst verwende R15 als Standard und teile dies mit), Händigkeit, Schleife oder Einzelaktion, grobe Dauer und welche Gameplay-Elemente benötigt werden (Trefferframe, Ballfreigabe, Schritte). Beginne sofort mit dem Bauen, wenn die Anfrage klar ist.
- Bewegung in Phasen unterteilen, bevor Zahlen geschrieben werden. Fast jede Aktion ist: Bereit → Antizipation → Aktion → Durchschwung → Erholung. Lies
references/motion-cookbook.mdfür das Genre, das du bearbeitest (Kampf, Sport, Bewegungsloops, Akrobatik, R6-Spezifika); es enthält Zeittabellen und Posenrezepte. - Spezifikation schreiben in
<name>.json. Beginne mit der nächstgelegenen Datei inexamples/anstatt bei Null. - Bauen:
node <skill>/scripts/ranim.cjs <name>.json --out out(mehrere Spezifikationen können übergeben werden; sie werden als Tabs in einer Vorschau angezeigt). Benötigt nur Node, keine Pakete. - Den Bericht auf stdout lesen. Er listet auf, wo sich Kopf, Hände und Füße an jedem Key tatsächlich befinden (Studs: R = rechts vom Charakter, U = über dem Boden, F = vorne) und druckt
WARN-Zeilen. Verwende die Positionen, um die Absicht zu überprüfen: Ist die Faust wirklich vor der Brust, ist der Fuß auf Ballhöhe? out/storyboard-<Name>.pngmit dem Read-Tool ansehen (jeder Key aus einer ¾-Ansicht und einer Seitenansicht). Wenn kein PNG erzeugt wurde, mache einen Screenshot vonout/preview.htmlmit einem Headless-Browser oder lese das SVG. Vergleiche jedes Panel mit der Phase, die du beabsichtigt hast.- Korrigieren und neu bauen, bis die Posen klar erkennbar sind und die Warnungen verschwunden oder bewusst akzeptiert sind. Zwei oder drei Runden sind normal.
- Liefern: die interaktive
out/preview.html(als Artefakt veröffentlichen oder die Datei senden), plusout/<Name>.rbxmxundout/<Name>.lua. Zeige das Storyboard-Bild inline an, wenn möglich. Erkläre dem Benutzer kurz, wie es in Studio geladen wird (siehe unten) und welche Animationsereignisse existieren.
Bewegungsspezifikation
{
"name": "JabCross", // wird zum KeyframeSequence-Namen und Dateinamen
"title": "Jab-Cross-Kombo", // wird im Vorschauprogramm angezeigt
"rig": "R15", // "R15" oder "R6"
"priority": "Action", // Idle | Movement | Action | Action2..4 | Core
"loop": false,
"description": "Ein oder zwei Sätze, die neben der Vorschau angezeigt werden.",
"keys": [
{ "t": 0, "label": "Bereit", "note": "Wird in der Phasenliste angezeigt.",
"pose": { "UpperTorso": { "turnR": 10, "bendFwd": 8 },
"LeftUpperArm": { "fwd": 50, "out": 8 }, "LeftLowerArm": { "bend": 120 },
"LeftFoot": "flat" } },
{ "t": 0.1, "label": "Jab", "ease": "out", "copy": "Bereit",
"pose": { "LeftUpperArm": { "fwd": 86, "in": 22 }, "LeftLowerArm": { "bend": 6 } } },
{ "t": 0.8, "label": "Erholen", "copy": "Bereit" }
],
"markers": [ { "t": 0.1, "name": "Hit", "value": "jab" } ],
"props": [ { "type": "ball", "radius": 0.6, "color": "#e07a2c", "keys": [ ... ] } ]
}
(Kommentare dienen nur der Erklärung; die Datei muss reines JSON sein.)
Optionale Felder auf oberster Ebene: fps (Standard 30; verwende 60 für sehr schnelle Bewegungen), duration (Standard ist der letzte Key), grounding ("off" um die Höhe manuell zu steuern), mirror: true (den gesamten Clip links/rechts spiegeln, z. B. eine Rechtsfuß-Version), endKeyframe: true.
Keys
tin Sekunden (auf einen Frame gerundet). Der erste Key ist bei 0.posebildet Gelenkname → Kanäle in Grad ab. Ein Gelenk, das in einem Key weggelassen wird, wird einfach durch diesen Key hindurch interpoliert. Keys zwischen zwei anderen können daher nur die relevanten Gelenke erwähnen. Ein Gelenk, das nie erwähnt wird, bleibt in Ruhestellung und wird nicht exportiert; eines, das erst nach Key 0 zum ersten Mal erwähnt wird, beginnt in Ruhestellung (0°).copy: das Label oder der Index eines früheren Keys. Die Pose beginnt als Kopie undposeüberschreibt Teile davon."mirror": truemitcopyvertauscht links und rechts, so werden Geh-/Laufzyklen aus einem halben Schritt erstellt.easeformt das Segment das diesen Key verlässt:smooth(Standard, lässt sich natürlich ohne Überschwingen ausklingen),linear,in(beginnt langsam, endet schnell: Aufladebewegungen, die in einen Schlag münden),out(beginnt schnell, wird langsam: Aufprall),inOut,hold,overshoot,anticipate,bounce,elastic.lift: Höhe in Studs des tiefsten Körperpunkts über dem Boden an diesem Key (Standard 0). So werden Sprünge gemacht; siehe Bodenhaftung.
Gelenke und Kanäle
Winkel sind anatomisch und das gleiche Wort bedeutet auf beiden Seiten des Körpers dasselbe, daher sind für eine gespiegelte Pose keine Vorzeichenwechsel erforderlich. Jeder Kanal hat einen Alias für die entgegengesetzte Richtung; verwende, was natürlich lesbar ist.
| Gelenke | Kanäle (Alias für die entgegengesetzte Richtung) |
|---|---|
Wurzel: LowerTorso (R15), Torso (R6) | bendFwd (bendBack), turnL (turnR), leanR (leanL), moveFwd (moveBack), moveR (moveL), moveUp (moveDown) in Studs |
Wirbelsäule: UpperTorso, Head | bendFwd (bendBack), turnL (turnR), leanR (leanL) |
Obere Gliedmaßen: Left/RightUpperArm, Left/RightUpperLeg; R6 Left Arm, Right Arm, Left Leg, Right Leg | fwd (back) schwingt das Glied nach vorne/oben, out (in) weg vom / quer über den Körper, twistOut (twistIn) rollt es um seine eigene Länge |
Left/RightLowerArm, Left/RightLowerLeg | bend: Ellenbogen und Knie in ihrer natürlichen Richtung (0 = gestreckt) |
Left/RightHand, Left/RightFoot | fwd (back), out (in), twistOut (twistIn). Füße akzeptieren auch den String "flat" |
Orientierungspunkte: Arm fwd: 90 zeigt geradeaus, fwd: 180 gerade nach oben, out: 90 ist eine T-Pose. Bein fwd: 90 ist ein Fronttritt auf Hüfthöhe. Rotationen setzen sich von Eltern zu Kind fort, daher trägt die Drehung der Brust die Arme mit sich; drehe den Head in die entgegengesetzte Richtung, um die Augen auf dem Ziel zu halten.
R6 hat sechs Teile und keine Ellbogen, Knie, Hände oder Füße, daher kommt die Silhouette aus den Winkeln des Rumpfes und der ganzen Gliedmaßen; übertreibe ein wenig. R6-Gliedmaßennamen enthalten ein Leerzeichen ("Right Arm").
Bodenhaftung
Standardmäßig senkt oder hebt die Engine die Wurzel in jedem Frame so, dass der tiefste Punkt des Körpers genau lift Studs über dem Boden liegt. Konsequenzen:
- Kniebeugen, Ausfallschritte und Spagate senken automatisch die Hüfte; stimme die Hüfthöhe für eine stehende Pose nie von Hand ab.
"flat"an einem R15-Fuß löst das Sprunggelenk so, dass die Sohle flach aufliegt, egal was das Bein tut. Verwende es für jeden aufgesetzten Fuß; gib explizite Winkel ("back": 40= Zehen zeigen) für Füße in der Luft oder auf den Zehenspitzen.- Ein Sprung sind
lift-Werte an den in der Luft befindlichen Keys (Absprung klein, Höhepunkt am größten, 0 bei der Landung). Körperrotation in der Luft erfolgt über die Wurzel: Ein Rückwärtssalto ist derbendBackder Wurzel, der über die Keys von 0 → 360 läuft (Winkel sind kontinuierlich, daher ist 360 eine volle Drehung, nicht „zurück auf 0“). moveUpan der Wurzel wird ignoriert, solange die Bodenhaftung aktiv ist. Setze"grounding": "off"nur für Dinge wie Schwimmen oder Klettern, bei denen der Boden irrelevant ist.- Sprünge und Sprints im Spiel werden normalerweise von der Charaktersteuerung bewegt, nicht von der Animation. Für eine Animation, die während eines Gameplay-Sprungs abgespielt werden soll, posiere den Körper und lasse
liftbei 0. VerwendeliftundmoveFwdfür eigenständige Emotionen, Angriffe mit einem Hüpfer und Saltos. Wenn der Clip von seinem Startpunkt versetzt endet, warnt der Bericht, weil Roblox den Körper zurücksetzt, wenn die Spur stoppt.
Marker und Props
markerswerden zuKeyframeMarkers, die im Spiel mittrack:GetMarkerReachedSignal("Hit")gelesen werden. Setze einen auf jeden Frame, der für das Gameplay relevant ist: Trefferfenster, Ballkontakt oder -freigabe, Schritte, Soundhinweise.propssind nur für die Vorschau (sie werden nicht exportiert) und dienen dazu, die Bewegung im Verhältnis zu dem, womit sie interagiert, beurteilen zu können.type: "ball"mitradiusoder ein anderer Typ für einen Kasten mitsize: [x, y, z](ein Schwert ist ein langer, dünner Kasten).atist entweder ein Teilname (das Prop folgt diesem Teil;offset: [right, up, fwd]in den eigenen Achsen des Teils) oder ein fester Punkt[right, up, fwd]in Studs vom Bodenpunkt unter dem Charakter. Mit mehrerenkeysbewegt sich das Prop zwischen Ankerpunkten;arcfügt dem Segment, das diesen Key verlässt, einen parabelförmigen Anstieg hinzu (ein Wurf oder ein Pass). Sieheexamples/jump_shot.jsonundexamples/soccer_kick.json.
Was gut aussieht
- Lesbare Silhouetten. Jeder Key im Storyboard sollte allein an seiner Kontur erkennbar sein. Wenn zwei benachbarte Keys gleich aussehen, leistet einer von ihnen keine Arbeit.
- Kontrast im Timing. Langsame Antizipation, sehr schnelle Aktion (2 bis 4 Frames), ein kurzes Halten im Durchschwung, langsamere Erholung. Gleichmäßige Abstände zwischen den Keys sind der häufigste Grund, warum sich eine Bewegung schwerelos anfühlt.
- Der ganze Körper macht mit. Kraft beginnt in den Füßen und Hüften, dann Brust, dann Schulter, dann Hand oder Fuß. Gib den Hüften und der Brust im Aufladen eine Gegenrotation und lass den fernen Arm den nahen ausgleichen.
- Füße bleiben stehen. Ein aufgesetzter Fuß behält seine R- und F-Werte im Bericht von Key zu Key. Wenn er sich bewegen muss, hebe ihn in einem Key dazwischen an (ein Schritt).
- Null Warnungen, oder einen Grund für jede, die du behältst. Die Grenzen sind natürliche Gelenkbereiche; sie zu überschreiten bedeutet normalerweise, dass ein anderer Kanal beabsichtigt war.
Einbinden in Roblox Studio
Gib dem Benutzer beide Wege und die Ereignisnamen an.
- Befehlszeile (am schnellsten): Wähle das Rig im Explorer aus, öffne Ansicht → Befehlszeile, füge den gesamten Inhalt von
<Name>.luaein, drücke die Eingabetaste. Die KeyframeSequence erscheint imAnimSavesdes Rigs (oder in ServerStorage, wenn nichts ausgewählt ist), wo der Animationseditor sie zum Bearbeiten laden kann. - Datei: Ziehe
<Name>.rbxmxin die Studio-Ansicht oder klicke mit der rechten Maustaste auf einen Dienst → Aus Datei einfügen. - Veröffentlichen: Um sie in einem Live-Spiel abzuspielen, muss sie hochgeladen werden: Öffne sie im Animationseditor und veröffentliche sie, oder klicke mit der rechten Maustaste auf die KeyframeSequence → In Roblox speichern, dann verwende die resultierende Asset-ID in einem
Animation-Objekt undAnimator:LoadAnimation. Für schnelle lokale Tests in Studio gibtgame:GetService("KeyframeSequenceProvider"):RegisterKeyframeSequence(seq)eine temporäre ID zurück. Studios Menüs ändern sich von Zeit zu Zeit; wenn ein Schritt nicht mit dem übereinstimmt, was der Benutzer sieht, sage dies und suche nach der aktuellen Formulierung, anstatt darauf zu bestehen.
Der Export ist gebacken: ein Keyframe pro Frame mit linearem Easing, sodass Studio genau das abspielt, was die Vorschau auf jedem Rig dieses Typs zeigt. Es werden nur Gelenke geschrieben, die die Spezifikation animiert, sodass eine Nur-Oberkörper-Animation die Beine für den Standard-Lauf freilässt. Die R15-Ausgabe enthält AuthoredHipHeight, damit sie auf Avatare anderer Proportionen umgesetzt werden kann.
Dateien
scripts/ranim.cjs— Engine, Vorschau und Export in einer Datei. Auch als Modul verwendbar:const R = require('.../ranim.cjs'); const c = R.compile(spezifikation); R.report(c); R.sample(c, t).scripts/selftest.cjs— Überprüft die Gelenkmathematik gegen Roblox' Motor6D-Formel. Führe es nach Änderungen an der Engine aus.examples/—soccer_kick,jump_shot(Sport mit Ball-Props),jab_cross(R15 Kampf),r6_sword_slash(R6 Kampf mit einer Waffe),backflip(Ganzkörperrotation und ein Sprung),r6_run(gespiegelter Loop).references/motion-cookbook.md— Zeittabellen und Posenrezepte nach Genre. Lese den relevanten Abschnitt, bevor du mit dem Erstellen beginnst.