update rules

This commit is contained in:
Joe 2026-02-02 14:05:11 -06:00
parent 4c390fdd37
commit d5522b2fef
8549 changed files with 11783 additions and 1888 deletions

View file

@ -0,0 +1,67 @@
---
title: Animation capture
description: Animation Capture in the Animation Editor allows you to generate high-quality, realistic animations for faces and bodies.
---
import BetaAlert from '../includes/beta-features/beta-alert.md'
You can record or upload video content to the [Animation Editor](../animation/editor.md) to quickly capture movement and expressions as animation keyframes. These tools can create unique and realistic animations within minutes while providing access to the animation keyframes for additional adjustments.
The animation capture tools allow you to:
- [Record your face](#face) with a webcam to puppeteer characters with [animation compatible heads](../art/characters/facial-animation/index.md).
- [Upload full-body video content](#body) to generate high quality realistic animations for an entire character.
## Face
**Animation Capture - Face** allows you to use your webcam to puppeteer rigs with [animation compatible heads](../art/characters/facial-animation/index.md) and generate corresponding keyframes to your movement. With the ability to record up to 60‑second animations, you can quickly provide both your playable and nonplayable characters the means to realistically grin, raise their eyebrows, drop their jaw, or any other expression necessary for your experience.
<BetaAlert betaName="Face Capture" leadIn="To ensure that you're able to utilize your camera to record and create facial animations, you must first enable the beta feature through " leadOut="." components={props.components} />
Before you begin to record your face, ensure that you're in a well lit room close enough to your camera so that your face is in the center of your camera's recording frame. This increases your camera's ability to distinguish you from your surroundings so that you can accurately puppeteer your avatar and create high-quality animations.
1. From the toolbar's **Avatar** tab, click **Animation**. The [Animation Editor](../animation/editor.md) window displays.
2. In the 3D viewport or the [Explorer](../studio/explorer.md) hierarchy, select the rig you want your video to animate. Enter a new animation name in the dialog window and click the **Create** button.
3. Navigate to the **track list** and click the **Face Capture** button. A popup displays asking you to acknowledge that you consent to the collection of your facial movements to enable the feature and camera access.
<img src="../assets/animation/face-recorder/Face-Recorder-Button.jpg"
width="80%" />
4. <Chip label="OPTIONAL" size="small" variant="outlined" /> If you have multiple cameras, choose which camera you want to use to record.
5. In the controls widget in the 3D viewport, click the red circle. Your camera begins recording your facial movements.
<img src="../assets/animation/face-recorder/Ready-Button.jpg" width="150" />
6. When you finish your recording, click either the red square or countdown timer. Keyframes that correspond to your facial movement display within the timeline.
<img src="../assets/animation/face-recorder/Countdown-Button.jpg" width="150" />
7. <Chip label="OPTIONAL" size="small" variant="outlined" /> If you'd like to delete the recording and try again, click **Re‑Record**.
After you finish your recording, you can [fine-tune](../animation/editor.md#keyframes) the keyframes, [save](../animation/editor.md#save-an-animation) your animation, then [export](../animation/editor.md#export-an-animation) it to use across all of your experiences.
## Body
The **Animation Capture - Body** allows you to quickly generate high-quality, realistic full-body animations for your R15 rigs by uploading videos to use to track the body's movement and generate corresponding keyframes. This significantly speeds up the manual process of creating animations, and allows you to personalize your avatars and NPCs with life-like mannerisms in a few minutes.
<BetaAlert betaName="Live Animation Creator" leadIn="To import a video for animation creation, you must first enable the beta feature through " leadOut="." components={props.components} />
Before you import a video to the **Animation Editor**, ensure the `.mp4` or `.mov` file meets the following requirements:
- It includes just one person who is well-lit and visible throughout the video.
- It only contains a continuous single shot that's less than 15 seconds from a stable camera.
- It adheres to Roblox's [Community Rules](https://en.help.roblox.com/hc/articles/203313410) and [Terms of Use](https://en.help.roblox.com/hc/articles/115004647846).
To import a video to create an animation:
1. From the toolbar's **Avatar** tab, click **Animation**. The [Animation Editor](../animation/editor.md) window displays.
2. In the 3D viewport or the [Explorer](../studio/explorer.md) hierarchy, select the R15 rig you want your video to animate. Enter a new animation name in the dialog window and click the **Create** button.
3. Navigate to the **media and playback controls** and click the **&ctdot;** button, then navigate to **Import**&nbsp;⟩ **Live&nbsp;Animation&nbsp;Creator**.
<img src="../assets/animation/live-animation-creator/Media-Playback-Controls.jpg"width="330" />
4. In the popup dialog, click the **Choose Video** button.
5. Select the video you want to import from your local machine, then click the **Open** button. After about a minute, keyframes that correspond to movement in your video display within the timeline.
After your import is successful, you can [save](../animation/editor.md#save-an-animation) and [export](../animation/editor.md#export-an-animation) your animation to use across all of your experiences.

View file

@ -0,0 +1,164 @@
---
title: Curve Editor
description: Curve Editor is a curve-based animation editing interface that lets you see and modify a rig's position and orientation.
comments: There are some opportunities to improve or add images/videos in this doc. Also some opportunity to create a "Using Curve Editor" use-case based article that'll quickly get an animator up to speed on the curve editor UI without the math.
---
The **Curve Editor** is a curve-based animation editing interface within the [Animation Editor](../animation/editor.md) that allows you to see and modify how a rig's position and orientation changes between keyframes through color‑coded curve graphs. It allows you to define independent tracks for the **X**, **Y** and **Z** angles, providing additional levels of control to make your animations more fluid and realistic.
<GridContainer numColumns="2">
<figure>
<img src="../assets/animation/curve-editor/Dope-Sheet-Editor.png" />
<figcaption>Dope Sheet Editor</figcaption>
</figure>
<figure>
<img src="../assets/animation/curve-editor/Curve-Editor-Example.png" />
<figcaption>Curve Editor</figcaption>
</figure>
</GridContainer>
Instead of using the default dope sheet editor's method of manually moving the scrubber from one frame to another to see how a rig's position and orientation change over time, the Curve Editor lets you quickly reference position and orientation values of your selected tracks through the **position ruler** on the left side of the timeline and the **rotation ruler** on the right side of the timeline.
<img
alt="Curve Editor Overview"
src="../assets/animation/curve-editor/UI-Overview.png"
width="780" />
## Open the Curve Editor
You can switch the editor's timeline between the dope sheet editor and the Curve Editor at any time.
1. Open the [Animation Editor](./editor.md) from Studio's **Avatar** tab or the **Window**&nbsp;⟩ **Avatar** menu.
<img src="../assets/studio/general/Toolbar-Animation.png" width="800" alt="Animation Editor indicated in Studio's toolbar" />
2. <Chip label="IMPORTANT" size="small" variant="outlined" color="warning" /> Studio automatically converts [quaternions](https://en.wikipedia.org/wiki/Quaternion) to [Euler angles](https://en.wikipedia.org/wiki/Euler_angles) when you open the Curve Editor, so it's important that you verify your rotation type **before** you switch to the Curve Editor. Once you convert quaternions to Euler angle tracks, it's impossible to convert them back into quaternions.
1. In the top-right corner of the editor window, click the gear icon. A contextual menu displays.
<img alt="Gear Icon" src="../assets/animation/curve-editor/Gear-Icon.png" width="600" />
2. Hover over **Default Rotation Type**, then select either **Euler Angles** or **Quaternions**. Your rotation type sets to your choice and becomes the default rotation type for future projects.
3. In the top-left corner of the **timeline**, click the **Curve Animation** icon. A popup window displays to confirm that your `Class.KeyframeSequence` clip will convert to a `Class.CurveAnimation` clip.
<img alt="Opening Curve Editor" src="../assets/animation/curve-editor/Opening-Curve-Editor.png" width="800" />
If you kept the default rotation type of Euler angles, Studio automatically converts any pre-existing quaternions to Euler angles following the [Euler angles order](#euler-angles-order) setting. Because `Class.KeyframeSequence|KeyframeSequences` work with quaternions and curve animations work with Euler angles by default, your animation might appear slightly different between keyframes, especially if any of your Euler angles approach [Gimbal lock](https://en.wikipedia.org/wiki/Gimbal_lock).
<img alt="Convert Euler Angles" src="../assets/animation/curve-editor/Convert-Euler-Angles.png" width="600" />
If you set the rotation type to quaternions, the conversion to curves preserves the quaternions and the animation remains the same.
<img alt="Curve Editor Overview" src="../assets/animation/curve-editor/Convert-Quaternion-Angles.png" width="600" />
## Interpolation
Interpolation is Studio's process of "filling in" position and orientation values between your keyframes. This allows the rig to seamlessly animate from one orientation or position to another instead of disjointedly jumping between keyframes. While Euler angle curves interpolate between the values of each keyframe, quaternion curves interpolate from `0` to `1` over a set time. To illustrate this, the following images display the same `Class.KeyframeSequence` after you open the Curve Editor with either a Euler angle or a quaternion rotation type:
<GridContainer numColumns="2">
<figure>
<img src="../assets/animation/curve-editor/Euler-Angle-Curve.png" />
<figcaption>Euler Angle Curve</figcaption>
</figure>
<figure>
<img src="../assets/animation/curve-editor/Quaternion-Curve-Interpolation.png" />
<figcaption>Quaternion Curve</figcaption>
</figure>
</GridContainer>
For **Euler angle curves**, the height of each keyframe represents its orientation value over time. For example, the highest keyframe represents a rotation of about 120 degrees around the **X** axis, and the lowest keyframe represents a rotation of about -10 degrees. For **quaternion curves**, each segment represents orientation changing between keyframes, and the line displays the interpolation between them. In the previous example, the animation starts from orientation A, then interpolates linearly to orientation B. Once it is at B, the interpolation starts again from orientation B to orientation C, then continues with this pattern until the rig reaches its final orientation.
You can modify how the Curve Editor handles interpolation for both Euler angle curves and quaternion curves by [setting tangents](#set), [changing the interpolation mode](#interpolation-mode), or by [generating interpolation curves](#generate-interpolation-curves) between two or more keyframes.
### Tangents
The Curve Editor provides **tangents**, or handles, that let you quickly adjust the interpolation either before or after a keyframe. Euler angle curves have a tangent both before and after the keyframe while quaternion curves have one tangent at the beginning and another at the end of a segment. The initial tangent controls the interpolation after the keyframe and the secondary tangent controls the interpolation before the keyframe. For example:
<GridContainer numColumns="2">
<figure>
<img src="../assets/animation/curve-editor/Euler-Angle-Curve-Tangents.png" />
<figcaption>Euler Angle Curve Tangents</figcaption>
</figure>
<figure>
<img src="../assets/animation/curve-editor/Quaternion-Curve-Tangents.png" />
<figcaption>Quaternion Curve Tangents</figcaption>
</figure>
</GridContainer>
<Alert severity="info">
For quaternion curve tangents, no matter how much you adjust each tangent, each segment always begins at `0` and ends at `1`. Although each segment of a quaternion curve graph is disconnected from subsequent segments, the two keyframes within the same frame always represent the same orientation.
</Alert>
Tangents change appearance when you set them to a new position. For example, when you manually set a tangent, the handle displays as a white circle, otherwise an unset tangent displays as a clear circle. For keyframes with two tangents, you can manually set either one or both tangents, and their appearance changes accordingly.
Tangents change appearance when you set them to a new position; an unset tangent displays as a clear circle, and a set tangent displays as a white circle. Studio automatically calculates the position for unset tangents based on the position of any set tangents. For instance, if you only set one tangent and leave the other unset, the unset tangent aligns with its opposite tangent:
<img
alt="Tangent Image"
src="../assets/animation/curve-editor/Tangent.png"
width="320" />
#### Set
To set a tangent:
1. Click and drag the tangent in the direction you want to pull the curve. The curve adjusts based on the location of your cursor.
2. Release the tangent. The interpolation between keyframes adjusts accordingly.
3. <Chip label="OPTIONAL" size="small" variant="outlined" /> If you set one tangent and want to align the unset tangent horizontally, right-click the unset tangent and select **Set&nbsp;Tangent&nbsp;to&nbsp;Zero** from the contextual menu.
#### Reset
If you ever set a tangent to a new position and the resulting interpolation is undesirable, you can always use "auto‑tangent mode" to clear a tangent's value and reset it back to its default interpolation behavior.
1. Right-click on a tangent. A contextual menu displays.
2. Select **Set Tangent To Zero**. The tangent resets to its default interpolation behavior.
### Interpolation mode
Interpolation mode is the rate at which an animation moves between different keyframe positions within the animation. There are three interpolation modes available for curve animations:
- **Linear** (default) — Moves at a constant speed from one keyframe to another.
- **Constant** — Removes interpolation between the selected keyframe and next keyframe, causing the animation to "snap" from keyframe to keyframe.
- **Cubic** — Eases in and/or out of the animation. Cubic is the only mode that allows you to define tangents.
To change interpolation mode:
1. Right-click a keyframe. A contextual menu displays.
2. Hover over **Interpolation Mode**, then select either **Linear**, **Constant**, or **Cubic**. The interpolation mode changes the curve following the keyframe.
<img
alt="Interpolation Mode"
src="../assets/animation/curve-editor/Interpolation-Mode.png"
width="600" />
### Generate interpolation curves
For curve animations, bounce and elastic easing styles are not available as standard interpolations like they are for `Class.KeyframeSequence|KeyframeSequences`. However, when you convert a `Class.KeyframeSequence` to a curve animation, Studio automatically adds additional keyframes to your animation to keep the animation intact, and you can select two or more keyframes and generate an **interpolation curve** that removes and replaces any of their intermediate keyframes to mimic bounce and elastic easing behavior.
To generate interpolation curves:
1. Select two or more keyframes. Each keyframe you select highlights.
2. Right-click one of these keyframes. A contextual menu displays.
3. Hover over **Generate Curve**, then over **Bounce** or **Elastic**, and then select either **Out**, **In**, or **InOut**. An interpolation curve between your selected keyframes generates according to your settings.
- **Out** — The motion is faster at the beginning and slower toward the end of the keyframe range.
- **In** — The motion is slower at the beginning and faster toward the end of the keyframe range.
- **InOut** — **In** and **Out** on the same tween, with **In** at the beginning and **Out** taking effect halfway through the keyframe range.
## Euler angles order
When you're working with Euler angles, Studio represents the **X**, **Y**, and **Z** axes through three channel values that follow a specific order to move your rig from its starting orientation to its next orientation. Each order is named after the [matrix multiplications](https://en.wikipedia.org/wiki/Matrix_multiplication) to get to the final orientation. For example, an **XYZ** order (**X**×**Y**×**Z**) means that the rig moves starting on the **Z** axis, then the **Y** axis, then the **X** axis.
How an animation changes when you set Euler angles order is dependent on **when** you change the order:
- If you load a `Class.KeyframeSequence` or a `Class.CurveAnimation` with a set quaternion rotation type then change the order, the new order doesn't affect the animation. This is because Studio uses quaternions to configure changes in your rig's orientation using the shortest path possible between its starting orientation to its next orientation. However, this method does affect how the quaternions of each keyframe transform into **X**, **Y**, and **Z** angles in the track list, which might visually affect the values within the timeline without affecting the animation itself.
- If you change the order of an existing Euler angle track, the animation might change since Studio preserves the values of each keyframe. This means that the ordered path Studio takes to change your rig's orientation from its starting orientation to its next orientation changes with the Euler angles order.
To set the Euler angles order:
1. In the top-right corner of the editor window, click the gear icon. A contextual menu displays.
<img alt="Gear Icon" src="../assets/animation/curve-editor/Gear-Icon.png" width="600" />
2. Hover over **Default Euler's Angles Order**, then select either **XYZ**, **XZY**, **YXZ**, **YZX**, **ZXY**, or **ZYX**. Your Euler angles order changes accordingly.

View file

@ -0,0 +1,597 @@
---
title: Animation Editor
description: Animation Editor allows you to design and publish custom animations on rigs.
---
The **Animation Editor**, accessible from Studio's **Avatar** tab or **Window**&nbsp;⟩ **Avatar** menu, allows you to design and publish custom animations on rigs. A rig is an object with individual sections connected by joints. You can move these joints to [create poses](#create-poses) and then smoothly animate the rig from pose to pose.
<img src="../assets/studio/general/Toolbar-Animation.png" width="800" alt="Animation Editor indicated in Studio's toolbar" />
## Interface
<img src="../assets/animation/animation-editor/Editor-Sections-Labeled.png"
width="80%" />
### Media and playback controls
<table>
<tr>
<td><img src="../assets/animation/animation-editor/Controls-Animation-Name.png"
width="100%" /></td>
<td>The name of the animation.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Controls-File-Menu.png"
width="100%" /></td>
<td>
Opens a contextual menu with the following menu items:
<ul>
<li>**Load**</li>
<li>**Save**</li>
<li>**Save As**</li>
<li>**Import**</li>
<li>**Export**</li>
<li>**Create New**</li>
<li>**Set Animation Priority**</li>
</ul>
</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Controls-First-Key.png"
width="100%" /></td>
<td>Moves the scrubber to the first key.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Controls-Previous-Key.png"
width="100%" /></td>
<td>Moves the scrubber to the previous key.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Controls-Preview-Reverse.png"
width="100%" /></td>
<td>Previews the animation in reverse.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Controls-Pause.png"
width="100%" /></td>
<td>Pauses the animation.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Controls-Preview.png"
width="100%" /></td>
<td>Previews the animation.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Controls-Next-Key.png"
width="100%" /></td>
<td>Moves the scrubber to the next key.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Controls-Last-Key.png"
width="100%" /></td>
<td>Moves the scrubber to the last key.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Controls-Looping.png"
width="100%" /></td>
<td>Toggles looping for the animation.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Controls-Position-Indicator.png"
width="100%" /></td>
<td>The **position indicator** that displays the timeline unit for the position of the scrubber in **seconds:frames**.</td>
</tr>
</table>
### Timeline
<table>
<tr>
<td><img src="../assets/animation/animation-editor/Timeline-Scrubber-Bar.png"
width="100%" /></td>
<td>A scrubber that marks the current frame position.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Timeline-Time-Units.png"
width="100%" /></td>
<td>Time units that allow you to move the scrubber to a precise time unit.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Timeline-Keyframe.png"
width="100%" /></td>
<td>A keyframe that marks the change in position or orientation of a part.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Timeline-Expand-Contract.png"
width="100%" /></td>
<td>Either expands or contracts the time unit marks.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Timeline-Options-Menu.png"
width="100%" /></td>
<td>
Opens a contextual menu with the following menu items:
<ul>
<li>**Timeline Unit**</li>
<li>**Frame Rate: 30fps**</li>
<li>**Show <a href="../animation/events.md">Animation Events</a>**</li>
<li>**Snap To Keys**</li>
</ul>
</td>
</tr>
</table>
### Track list
<table>
<tr>
<td><img src="../assets/animation/animation-editor/Track-List-Rig-Name.png"
width="100%" /></td>
<td>The name of the rig.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Track-List-IK-Button.png"
width="100%" /></td>
<td>Opens the **Manage IK** window.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Track-List-Add-Tracks.png"
width="100%" /></td>
<td>Opens a contextual menu of additional tracks you can add to the track list. </td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Track-List-Track-Name.png"
width="100%" /></td>
<td>The track displaying the name, position, and rotation of the part that
has been moved or rotated to a new position or orientation.</td>
</tr>
<tr>
<td><img src="../assets/animation/animation-editor/Track-List-Track-Options.png"
width="100%" /></td>
<td>
Opens a contextual menu with the following menu items:
<ul>
<li>**Add Keyframe**</li>
<li>**Delete Track**</li>
</ul>
</td>
</tr>
</table>
## Create an animation
You can only create animations using rigs. If you don't have a rig available, insert a pre-built rig using the [Rig Generator](../studio/rig-builder.md) tool. The pre-built rigs have all of the basic parts and mechanisms to
build a character animation.
If you have a rig, you can create a new animation for it using the following steps:
1. From the toolbar's **Avatar** tab, click **Animation**.
2. Select the rig you want to create an animation for to display the creation dialog.
<img src="../assets/animation/animation-editor/Create-Animation-Dialog.png" width="380" />
3. In the **Animation Name** field, enter a new animation name, then
click the **Create** button. The **Animation Editor** window displays
the [media and playback controls](#media-and-playback-controls), [timeline](#timeline), and [track list](#track-list).
From here, you can begin [creating poses](#create-poses)
for your rig and modifying the animation settings, such as [looping
the animation](#loop-an-animation) or [setting its
priority](#set-a-priority).
### Create poses
An animation consists of different **poses**, or specific positions and orientations of `Class.Bone` or `Class.MeshPart` objects within a rig. You can create poses by moving or rotating bones or meshes, such as the rig's hands, feet, or torso. After you create multiple poses on different positions of the timeline, the **Animation Editor** runs between them with your [easing settings](#easing) to smoothly animate the rig from pose-to-pose.
For example, a simple animation where a humanoid character turns
to look 45° to the left has two poses:
- The initial position looking forward.
- The turned position looking left.
<video src="../assets/animation/animation-editor/Animation-Poses.mp4" controls width="80%"></video>
To create a pose:
1. In the **Explorer** window, select the rig and expand its child instances to access the bones or meshes.
2. In the **Animation Editor** window, navigate to the timeline, then
click-and-move the **scrubber** to the frame position where you
want to set the pose. By default, Roblox represents timeline units as
**seconds:frames** and animations run at 30 frames per second. For example, 0:15 indicates ½ second.
<img src="../assets/animation/animation-editor/Scrubber-0-15.png" width="60%" />
3. In the **viewport**, hover your mouse over **rig** and select a bone or mesh. You can also select the ⊕ icon on the timeline and click **Add All** to add all bones or meshes to the animation.
<img src="../assets/modeling/skinned-meshes/Animation-Editor-Add-Tracks.png" width="60%" />
4. Move or rotate the bone or mesh to a new orientation. For bones, you can rotate them to pose the rig along the created bone joints.
<video controls src="../assets/modeling/skinned-meshes/Transform-Demo-Skinned.mp4" width="100%"></video>
<Alert severity="info" variant="standard">
When creating poses, you can toggle between **Move** and **Rotate**
modes by pressing <kbd>R</kbd>. These modes work exactly like moving and rotating base objects, including the snap settings and incremental values located in Studio's toolbar.
</Alert>
5. Continue moving or rotating bones or meshes until you get the desired pose.
Whenever you adjust a specific bone or mesh, a **new track** displays in the track list, and a **new keyframe** displays on the **timeline** for that bone more mesh at that specific frame position.
<img src="../assets/animation/animation-editor/Track-Keyframe-Added.png" width="80%" />
6. When you're ready to preview the animation, you can either:
- Navigate to the **Media and Playback Controls**, then click the
**Play** button.
<img src="../assets/animation/animation-editor/Controls-Preview.png"width="330" />
- Or press the **Spacebar**.
<Alert severity="info" variant="standard">
By default, the timeline displays a duration of 1 second (30 frames), but the final keyframe determines the animation's actual duration. To
add more time to the timeline, enter a new value in the right-side box of
the position indicator.
</Alert>
## Keyframes
Once you [create basic poses](#create-poses) for a rig,
fine-tuning individual keyframes can significantly improve the final
animation.
### Add keyframes
Whenever you change a part's position or orientation, a new keyframe
displays on the timeline. You can also add keyframes to a timeline
through the following methods.
To add a keyframe for a single part of the rig:
1. Navigate to the **timeline**, then move the **scrubber** to a new
position.
2. In the **track list**, navigate to the part's **track** and click
the **&ctdot;** button. A contextual menu displays.
<img
src="../assets/animation/animation-editor/Track-List-Track-Options.png"
width="330" />
3. Select **Add Keyframe**.
To add a keyframe for multiple parts of the rig:
1. Navigate to the **timeline**, then right-click in the dark region
above the tracks. A pop-up menu displays.
<img
src="../assets/animation/animation-editor/Add-Multiple-Keyframes.png"
width="500" />
2. Select **Add Keyframe Here**.
Note that the keyframes insert at the frame position closest to where you click,
not at the position of the scrubber.
### Move keyframes
You can increase or decrease the amount of time between keyframes by moving
either individual keyframes or every keyframe in a frame position.
To move a single keyframe:
1. Navigate to the **timeline** and click on any **gray keyframe**.
Both the **gray keyframe** and the **white keyframe** are now
surrounded with a blue border.
<img
src="../assets/animation/animation-editor/Select-Single-Keyframe.png"
width="500" />
2. Click-and-drag it to a new frame position.
To move every keyframe in a frame position:
1. Navigate to the **timeline** and click on the **white keyframe** in
the dark region above the tracks. Every keyframe in the frame
position is now surrounded with a blue border.
<img
src="../assets/animation/animation-editor/Select-Multiple-Keyframes.png"
width="500" />
2. Click-and-drag it to a new frame position.
### Duplicate keyframes
You can duplicate either a specific keyframe or multiple keyframes for
multiple parts into a new position in the timeline. This is particularly
useful for when you want to
To duplicate one or more keyframes:
1. Navigate to the **timeline** and select one or more keyframes. Every selected keyframe is now surrounded by a blue border.
1. Press <kbd>Ctrl</kbd><kbd>C</kbd> (<kbd>⌘</kbd><kbd>C</kbd>). Every selected keyframe copies to your clipboard.
1. Move the **scrubber** to a new frame position.
1. Press <kbd>Ctrl</kbd><kbd>V</kbd> (<kbd>⌘</kbd><kbd>V</kbd>). The keyframe(s) paste into the new frame position.
### Delete keyframes
To delete one or more keyframes, select the keyframe(s), then press
**Delete** or **Backspace**.
### Optimize keyframes
Animators can often generate many keyframes during the course of animation, especially when using various animation tools and features. To help reduce the number of unnecessary keyframes and make it easier to animate on the timeline, the **Animation Editor** provides tools for [automatic](#automatic-optimization) and [on-demand](#on-demand-optimization) keyframe optimization.
#### Automatic optimization
The **Animation Editor** automatically detects and removes unnecessary keyframes when creating [facial animations](../art/characters/facial-animation/animate-heads.md) and when [promoting a keyframe animation to a curve animation](../animation/curve-editor.md#open-the-curve-editor).
If 3 or more consecutive keyframes have the same value in a track, the **Animation Editor** removes the intermediary keyframes and keeps only the first and last keyframes.
If the track only contains keyframes with default values, such as an `Datatype.CFrame.identity|Identity Cframe`, or a `0` value for a curve animation, the entire track is removed from the animation.
#### On-demand optimization
<img
alt="Optimize Keyframes"
src="../assets/animation/animation-editor/Optimization-Preview.png"
width="90%" />
During animating, you can use the editor's **Keyframe Optimization** tool to quickly reduce the number of unnecessary keyframes. Keyframe Optimization prioritizes the least impactful keyframes first. You can adjust the number of keyframes using the slider.
While using the slider, you can preview the animation and scrub through the timeline to check your animation but you can not perform editing operations, such as changing keyframe values or adding tracks.
To access the **Optimize Keyframes** tool:
1. In the **Animation Editor**, click \***\*&ctdot;\*\*** button and select **Optimize Keyframes**. A dialog box with a slider displays.
<img
alt="Optimize Keyframes"
src="../assets/animation/animation-editor/Optimize-Keyframes.png"
width="20%" />
2. Move the slider to the desired number of keyframes. You can preview and playback the animation to verify the optimization.
<img
alt="Optimize Keyframes"
src="../assets/animation/animation-editor/Optimization-Slider.png"
width="40%" />
3. Click **OK** when complete.
### Easing
For each keyframe in the [Animation Editor](../animation/editor.md), you can choose both an
[easing style](#easing-style) and an [easing direction](#easing-direction).
#### Easing style
**Easing style** is the rate at which an animation moves between different frame
positions within the animation. By default, a part will move and/or rotate from
one keyframe to the next in an even, steady motion known as **linear easing**.
In the following video, linear easing makes the character's turning animation
appear stiff and robotic.
<figure>
<video src="../assets/animation/animation-editor/Easing-Linear.mp4" controls width="100%"></video>
<figcaption>Linear easing</figcaption>
</figure>
While that may look appropriate for some motions, compare the following video
where **cubic easing** makes the animation of the character's motion appear more
natural.
<figure>
<video src="../assets/animation/animation-editor/Easing-Cubic.mp4" controls width="100%"></video>
<figcaption>Cubic easing</figcaption>
</figure>
To change the easing style for one or more keyframes:
1. Navigate to the **timeline** and select one or more keyframes. Every selected
keyframe is now surrounded by a blue border.
2. Right-click on a **keyframe with a border**. A pop-up menu displays.
3. Hover over **Easing Style**, then choose from the following options:
- **Linear** - Moves at a constant speed.
- **Constant** - Removes interpolation between the selected keyframe and
next keyframe. The animation will "snap" from keyframe to keyframe.
- **Cubic** - Eases in or out with cubic interpolation.
- **Elastic** - Moves as if the object is attached to a rubber band.
- **Bounce** - Moves as if the start or end position of the tween is bouncy.
#### Easing direction
**Easing direction** defines which end of the animation movement is affected by
the [easing style](#easing-style). By default, the motion is slower at the
beginning and faster toward the end of the animation.
To change the easing direction for one or more keyframes:
1. Navigate to the **timeline** and select one or more keyframes. Every selected
keyframe is now surrounded by a blue border.
1. Right-click on a **keyframe with a border**. A pop-up menu displays.
1. Hover over **Easing Direction**, then choose from the following options:
- **Out** - The motion will be faster at the beginning and slower toward the
end.
- **InOut** - **In** and **Out** on the same tween, with **In** at the
beginning and **Out** taking effect halfway through.
- **In** - The motion will be slower at the beginning and faster toward the
end.
## Loop an animation
To make an animation automatically loop, navigate to the [Media and
Playback Controls](#media-and-playback-controls) and click
the **Looping** button.
<img src="../assets/animation/animation-editor/Controls-Looping.png"
width="330" />
<Alert severity="info" variant="standard">
A looping animation doesn't interpolate between the final
keyframes and first keyframes. To make the animation loop smoothly,
<a href="#duplicating-keyframes">duplicate</a> the first
keyframes and use them as the final keyframes.
</Alert>
## Set a priority
An animation's **priority** (`Enum.AnimationPriority`) dictates when it will play in an
experience. For example, if you play an animation with a higher priority
than another animation that's already playing, the new animation will
override the old. For example, a "jump" animation should take priority over an "idle" animation so that a character doesn't perform both at the same time.
Roblox uses seven levels of priority, ordered here from highest to lowest:
<Grid container spacing={2} alignItems="center">
<Grid item XSmall={2} Medium={1} Large={1} XLarge={1}><img src="../assets/misc/Arrow-Highest.png" width="50" style={{float:"right"}} /></Grid>
<Grid item XSmall={10} Medium={11} Large={11} XLarge={11}>
**Action4**
</Grid>
</Grid>
<Grid container spacing={2} alignItems="center">
<Grid item XSmall={2} Medium={1} Large={1} XLarge={1}><img src="../assets/misc/Arrow-Higher.png" width="50" style={{float:"right"}} /></Grid>
<Grid item XSmall={10} Medium={11} Large={11} XLarge={11}>
**Action3**
</Grid>
</Grid>
<Grid container spacing={2} alignItems="center">
<Grid item XSmall={2} Medium={1} Large={1} XLarge={1}><img src="../assets/misc/Arrow-High.png" width="50" style={{float:"right"}} /></Grid>
<Grid item XSmall={10} Medium={11} Large={11} XLarge={11}>
**Action2**
</Grid>
</Grid>
<Grid container spacing={2} alignItems="center">
<Grid item XSmall={2} Medium={1} Large={1} XLarge={1}><img src="../assets/misc/Arrow-Neutral.png" width="50" style={{float:"right"}} /></Grid>
<Grid item XSmall={10} Medium={11} Large={11} XLarge={11}>
**Action**
</Grid>
</Grid>
<Grid container spacing={2} alignItems="center">
<Grid item XSmall={2} Medium={1} Large={1} XLarge={1}><img src="../assets/misc/Arrow-Low.png" width="50" style={{float:"right"}} /></Grid>
<Grid item XSmall={10} Medium={11} Large={11} XLarge={11}>
**Movement**
</Grid>
</Grid>
<Grid container spacing={2} alignItems="center">
<Grid item XSmall={2} Medium={1} Large={1} XLarge={1}><img src="../assets/misc/Arrow-Lower.png" width="50" style={{float:"right"}} /></Grid>
<Grid item XSmall={10} Medium={11} Large={11} XLarge={11}>
**Idle**
</Grid>
</Grid>
<Grid container spacing={2} alignItems="center">
<Grid item XSmall={2} Medium={1} Large={1} XLarge={1}><img src="../assets/misc/Arrow-Lowest.png" width="50" style={{float:"right"}} /></Grid>
<Grid item XSmall={10} Medium={11} Large={11} XLarge={11}>
**Core**
</Grid>
</Grid>
<br />
To set an animation to a different priority:
1. Navigate to the [Media and Playback Controls](#media-and-playback-controls)
and click the **&ctdot;** button. A
contextual menu displays.
1. Hover over **Set Animation Priority**, then choose your desired
priority setting.
## Save an animation
When you save an animation, Studio saves it as a
`Class.KeyframeSequence` object in `Class.ServerStorage` and adds a reference to your rig object. Saving your animation is meant to preserve your animation progress and work. If you intend to use an animation, [export it](#export-an-animation) before referencing the published animation in your experience.
To save an animation:
1. Navigate to the [Media and Playback Controls](#media-and-playback-controls)
and click the **&ctdot;** button. A
contextual menu displays.
<img src="../assets/animation/animation-editor/Controls-File-Menu.png"
width="330" />
2. Select **Save** or **Save As** to save the animation with a reference added to the **AnimSaves** object.
<img src="../assets/animation/animation-editor/Saved-Animation.png"
width="320" />
### Access local data
Roblox saves animation data locally to `Class.ServerStorage` to preserve your animation work. In most cases, your experience shouldn't directly access this local data and instead should reference a published animation.
In the rare cases that your experience requires accessing local data, reference the value of the `Class.ObjectValue` in your rig's AnimSaves folder rather than directly accessing the `Class.ServerStorage`. See the following examples:
```lua title="Access local animation data"
local myAnim = myRig.AnimSaves.Value.myAnimation
-- Accesses your local animation data with the value reference in your rig
```
```lua title="Incorrectly access local data"
local myAnim = ServerStorage.RBX_ANIMSAVES.myRig.myAnimation
-- Can conflict with other rigs sharing the same name
```
<Alert severity = 'warning'>
Since local data is stored in `Class.ServerStorage`, it doesn't replicate and isn't available from clients. If your clients need access to that data, you must move the `Class.KeyframeSequence` or `Class.CurveAnimation` objects and their descendants to `Class.ReplicatedStorage`.
</Alert>
### Migrate legacy data
The **Animation Editor** previously stored animation objects directly within a rig, not within `Class.ServerStorage`. If your experience references legacy animation objects in a rig, you can migrate this data to `Class.ServerStorage` using the animation migration tool, allowing you to [access local animation data](#access-local-data) in the same way.
To migrate your legacy animation data:
1. With the **Animation Editor**, select a rig with older animations that aren't saved in `Class.ServerStorage`. A migration window displays.
<img src="../assets/animation/animation-editor/Migrate-Animations.png" width = "65%" />
2. Select **Delete**, **Migrate**, or **Ignore** for each detected animation.
- **Delete**: Delete animations that are already published or no longer being used.
- **Migrate**: Migrate animations that are still in progress or that haven't yet been published.
- **Ignore**: Ignore animations if you have yet to update your experience's code to [access local data](#access-local-data) from `Class.ServerStorage`. Once updated, migrate these animations.
3. Press **OK** when complete.
## Export an animation
When you export an animation to Studio, it becomes available for use in
all experiences. This means that you only need to create an animation
once, then you can reuse it as many times as you want.
<Alert severity="warning">
If your animation will be used for a **default** Roblox character animation like jumping or running, ensure that you rename the final keyframe as outlined in the first step below.
</Alert>
To export an animation:
1. **(Important)** If the animation will be used to [replace a default character animation](../animation/using.md#replace-default-animations) like running or jumping, rename the final keyframe **End** as follows:
1. Right-click the final white keyframe symbol in the upper bar region and choose **Rename&nbsp;Key&nbsp;Keyframe** from the
contextual menu.
<img src="../assets/animation/animation-editor/Select-Final-Keyframe.png" width="500" />
2. Type **End** (case-sensitive) into the input field.
3. Click the **Save** button.
2. Navigate to the [Media and Playback Controls](#media-and-playback-controls)
and click the **&ctdot;** button.
<img src="../assets/animation/animation-editor/Controls-File-Menu.png"
width="330" />
3. Select **Publish to Roblox** from the contextual menu.
4. In the **Asset Configuration** window, enter an animation title and optional description.
5. **(Important)** If the animation will be used in any [group-owned](../projects/groups.md) experience, select the group from the **Creator** field.
6. Click the **Submit** button.
Once the upload is complete, you can copy the animation's asset ID
from the [Toolbox](../projects/assets/toolbox.md) for scripting custom animations or to replace default character animations, as outlined in [Use animations](../animation/using.md).
1. Click the **Creations** tab and select **Animations** from the dropdown menu.
2. Right-click the desired animation and select **Copy Asset ID** from the contextual menu.
3. See [Use animations](../animation/using.md) for instructions on how to play the animation from a script or use the animation as a default character animation.

View file

@ -0,0 +1,135 @@
---
title: Animation events
description: Animation Events are markers across the timeline span in the Animation Editor.
---
You can define animation **event markers** across the timeline span and use
`Class.AnimationTrack:GetMarkerReachedSignal()|GetMarkerReachedSignal()`
to detect those markers as the animation runs.
## Show events
By default, the event track isn't visible. To show the event track:
1. Navigate to the right of the **timeline**, then click the **Gear** icon.
A pop-up menu displays.
<img
src="../assets/animation/animation-editor/Timeline-Options-Menu.png"
width="330" />
2. Select **Show Animation Events**. This opens the **Animation Events** bar directly below the media and
playback controls.
<img
src="../assets/animation/animation-editor/Animation-Events-Bar.png"
width="600" />
You can now [create](#create-events), [detect](#detect-events), and
[duplicate](#duplicate-events) events.
## Create events
Event markers are visual indicators of where an animation event begins. After you create an event
marker, you can move it to any frame position on the timeline.
To create a new event marker:
1. Navigate to the **timeline**, then click-and-drag the **scrubber** to the
frame position where the event should occur.
2. Navigate to the **event track**, then click the **Edit Animation Events**
button. The **Edit Animation Events** dialog displays.
<img
src="../assets/animation/animation-editor/Animation-Events-Edit-Button.png"
width="600" />
3. In the **Edit Animation Events** dialog, click **+ Add Event**, then enter an
event name.
<img
src="../assets/animation/animation-editor/Animation-Events-Add-Event.png"
width="507" />
4. **(Optional)** In the **Parameter** field, enter a parameter string for the event.
5. Click the **Save** button. In the events bar within the timeline, a new
marker symbol displays at the frame position.
<img
src="../assets/animation/animation-editor/Animation-Events-Marker-In-Timeline.png"
width="700" />
## Detect events
To detect animation events in a `Class.LocalScript`,
connect a function to the `Class.AnimationTrack:GetMarkerReachedSignal()|GetMarkerReachedSignal()` function of `Class.AnimationTrack`. For example:
```lua
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
-- Create new "Animation" instance
local walkAnim = Instance.new("Animation")
-- Set its "AnimationId" to the corresponding animation asset ID
walkAnim.AnimationId = "rbxassetid://5432167890"
-- Load animation onto the animator
local walkAnimTrack = animator:LoadAnimation(walkAnim)
-- Connect "GetMarkerReachedSignal" event to a specific named keyframe
walkAnimTrack:GetMarkerReachedSignal("FootStep"):Connect(function(paramString)
print(paramString)
end)
```
<Alert
severity="info"
variant="standard">
You can specify a <b>Parameter</b> value for any event
marker within the **Animation Editor**. This lets you pass a custom <b>string</b>
(single value, comma-separated string, etc.) to the `Class.AnimationTrack:GetMarkerReachedSignal()|GetMarkerReachedSignal()` function, as illustrated by the <b>paramString</b> argument in the code example above. This string can then be parsed or converted, if necessary, and used for whatever action you wish to perform in the event.
</Alert>
## Duplicate events
As you create events, they become available for usage throughout the whole
animation, not only at the frame position where you originally created them. For
instance, you can create a "FootStep" event marker at the point where a
character's **left** foot touches down, then use the same event when the
character's **right** foot touches down.
To duplicate an event:
1. Navigate to the **timeline**, then click an **event marker** in the **event bar**.
<img
src="../assets/animation/animation-editor/Animation-Events-Marker-Selected.png"
width="700" />
2. Press <kbd>Ctrl</kbd><kbd>C</kbd> (<kbd>⌘</kbd><kbd>C</kbd> on Mac).
3. Click-and-drag the **scrubber** to the frame position where you want to
duplicate the event.
4. Press <kbd>Ctrl</kbd><kbd>V</kbd> (<kbd>⌘</kbd><kbd>V</kbd> on Mac).
<img
src="../assets/animation/animation-editor/Animation-Events-Marker-Pasted.png"
width="700" />
If the original event uses a parameter
but the duplicated event should use a modified parameter, perform the following
steps:
1. Right-click the duplicated event marker. A pop-up menu displays.
2. Select **Edit Animation** Event. The **Edit Animation Events** dialog
displays.
3. Make your changes, then click the **Save** button.
<Alert
severity="info"
variant="standard">
You can also duplicate events by clicking the <b>Edit Animation Events</b> button (just as if you were <a href="#create-events">creating a new event</a>), clicking <b>Add Event</b> in the pop-up menu, selecting the desired event from the dropdown, and clicking <b>Save</b>.
</Alert>

View file

@ -0,0 +1,34 @@
---
title: Animation in Roblox
description: An overview of all animation tools in Roblox Studio.
---
**Animation** is the process of applying motion to your characters, objects, and environments to create an engaging and dynamic experience. While there are many ways to make objects move and interact, animation in Roblox typically refers to customizing an expressive movement of a specific character, or group of parts, using the **Animation Editor** or **animation-related APIs**.
Animation can apply to any Roblox part or group of parts. Different types of objects can utilize various animation features. The following are the general categories of animatable objects:
- **Simple objects**, such as a basic part, can only animate changes across the part's single position or rotation property.
- **Rigs**, or parts connected by joints like `Class.Bone` or `Class.Motor6D`, can articulate positional and rotational movement between their joints, like elbows and wrists. Rigged models can take advantage of animation features like [inverse kinematics](#inverse-kinematics) to quickly and programmatically apply movement in response to environments and events.
- **R15 rigs**, rigs that incorporate the standardized [avatar character model](../characters/index.md#avatar-character-components), can use animations from Roblox's character animation library and other movement features, even if it's a player or non-player character model.
## Animation Editor
The [Animation Editor](../animation/editor.md) allows you to design and publish custom animations on rigs. You can move the joints that connect individual sections of a rig to create poses, and the **Animation Editor** smoothly animates the rig from pose-to-pose. As long as all moving parts are connected with `Class.Motor6D` objects, you can use the editor for both human and non-human rigs.
<video src="../assets/animation/inverse-kinematics/IK-Body-Part.mp4" controls width="80%"></video>
When creating animations, Studio provides the following features to animate effectively:
- Instantly create face and body animations through the [Animation Capture](../animation/capture.md) tool.
- Switch to the [Curve Editor](../animation/curve-editor.md) to access the curve-based animation UI and more control over your animation tracks.
- Make realistic animations by posing and animating `Class.Bone|Bones` of a [rigged mesh](../art/modeling/rigging.md).
## Inverse kinematics
You can use [inverse kinematics](../animation/inverse-kinematics.md) APIs to automatically create animations and poses based on environmental and external events. With inverse kinematics, you can procedurally generate various animation events, such as having a character's head track a bird flying in the sky, or making a character's arm automatically reach for a door knob when nearby.
## Animation events
An [animation event](../animation/events.md) is a specific point in an animation that triggers an action. You can define animation event markers across the **Animation Editor** timeline span, then use `Class.AnimationTrack:GetMarkerReachedSignal()` to detect those markers as the animation runs to perform specific actions, such as playing a sound effect whenever the user's foot touches the ground.

View file

@ -0,0 +1,199 @@
---
title: Inverse Kinematics
description: Inverse Kinematics is a technique in computer animation to make characters move and interact with their environment.
---
[Inverse Kinematics](https://en.wikipedia.org/wiki/Inverse_kinematics) (IK) is a common technique in computer animation to efficiently make characters move and interact realistically with their environment. The process of creating a realistic movement for a character often requires many iterations and minor adjustments of the various joints. With IK, you can pose and animate multiple character parts by posing or adjusting a single object.
This animation technique can provide solutions to the following examples:
<GridContainer numColumns="3">
<figure>
<video controls src="../assets/animation/inverse-kinematics/IK-Place-Hand.mp4" width="90%"></video>
<figcaption>Grab and pose a character's hand while automatically adjusting the related limbs, such as the wrist, elbow, and shoulder.</figcaption>
</figure>
<figure>
<video controls src="../assets/animation/inverse-kinematics/IK-Uneven-Surfaces.mp4" width="90%"></video>
<figcaption>Make a character's feet interact realistically on different surfaces and slopes.</figcaption>
</figure>
<figure>
<video controls src="../assets/animation/inverse-kinematics/IK-Drag-Accessory.mp4" width="90%"></video>
<figcaption>Grab and move a single target object to quickly create realistic interactions with your character and props.</figcaption>
</figure>
</GridContainer>
## IKControl
You can use an `Class.IKControl` to procedurally add IK to your character rigs outside of the **Animation Editor**. Studio allows you to programmatically apply IK to all characters, such as R15, Rthro, and custom imported skinned characters, to create realistic movement and interactions in your experience.
When adding an `Class.IKControl`, set the [required properties](#required-properties) correctly to avoid unexpected and unnatural animation results. As with all animation, [test your IKControls](#test-ikcontrols) to ensure that you achieve the desired behavior.
### Required properties
When adding a `Class.IKControl` to your character's `Class.Humanoid` or `Class.AnimationController`, you must set the following required properties to enable IK:
<table>
<thead>
<tr>
<th>Property</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>`Class.IKControl.Type|Type`</td>
<td>Specifies the behavior type of the IK control. See `Enum.IKControlType` for the list of behavior options. Common behavior types are `Position` or `Transform`.</td>
</tr>
<tr>
<td>`Class.IKControl.EndEffector|EndEffector`</td>
<td>A `Class.BasePart` or `Class.Bone` in your character rig that tracks toward the `Class.IKControl.Target|Target`. For example, you can set a **LeftHand** bone as a `Class.IKControl.EndEffector|EndEffector` to reach a doorknob object set as the `Class.IKControl.Target|Target`.</td>
</tr>
<tr>
<td>`Class.IKControl.Target|Target`</td>
<td>The object the `Class.IKControl.EndEffector|EndEffector` reaches or points toward. A `Class.IKControl.Target|Target` can be any object with a world position.</td>
</tr>
<tr>
<td>`Class.IKControl.ChainRoot|ChainRoot`</td>
<td>Defines the chain of `Class.BasePart|BaseParts` or `Class.Bone|Bones` that the `Class.IKControl` affects. All connected parts between the `Class.IKControl.ChainRoot|ChainRoot` and the `Class.IKControl.EndEffector|EndEffector` are affected by the `Class.IKControl` using the behavior type defined. <br /><br /> For example, if your character's **LeftHand** is set as the `Class.IKControl.Target|Target`, you can apply IK to the entire left arm by setting `Class.IKControl.ChainRoot|ChainRoot` to the **LeftUpperArm**. To apply IK just to the parts below the elbow, set `Class.IKControl.ChainRoot|ChainRoot` to the **LeftLowerArm**.</td>
</tr>
</tbody>
</table>
### Test IKControls
You can add and edit `Class.IKControl` programmatically or directly through the **Explorer**. You can even add and make changes to `Class.IKControl` during a Play test to quickly check how various properties affect a character's movements.
To quickly test your `Class.IKControl` using an `Class.Attachment` as a target:
1. From Studio's mezzanine, [initiate a playtest](../studio/testing-modes.md#playtesting).
2. In the **Explorer**, navigate to **Workspace** → your user's `Class.Model`. This `Class.Model` instance is named as your current Roblox account.
3. Click the **⊕** icon next to your character model's `HumanoidRootPart` and add an **Attachment**.
<img src="../assets/animation/inverse-kinematics/IK-Add-Attachment.png"
width="40%" />
4. Select the **Attachment** and use the **Move** tool to position the object in front of your character in the viewport.
<img src="../assets/animation/inverse-kinematics/IK-Move-Attachment.png"
width="40%" />
5. In the **Explorer** window, select the **⊕** icon next to your character's `Class.Humanoid` and add an **IKControl**.
<img src="../assets/animation/inverse-kinematics/IK-Humanoid-Add.png"
width="40%" />
6. Select the `Class.IKControl` and set the following property values in the **Properties** window:
1. **Type**: Select `Transform` from the dropdown.
2. **EndEffector**: Select your model's **LeftHand** `Class.MeshPart` in the **Explorer**.
3. **Target**: Select the newly created **Attachment** object in the **Explorer**.
4. **ChainRoot**: Select your model's **LeftUpperArm** `Class.MeshPart` in the **Explorer**.
<GridContainer numColumns="2">
<figure>
<img src="../assets/animation/inverse-kinematics/IK-IKControl-Property.png" width="80%" />
<figcaption>IKControl Properties</figcaption>
</figure>
<figure>
<img src="../assets/animation/inverse-kinematics/IK-Explorer-Humanoid.png" width="67%" />
<figcaption>Explorer - Character Model</figcaption>
</figure>
</GridContainer>
Your character's left arm should now reach for the target `Class.Attachment`. You can experiment with moving the `Class.Attachment` or editing the `Class.IKControl` properties to achieve different results.
<video controls src="../assets/animation/inverse-kinematics/IK-Drag-Hand.mp4" width="40%"></video>
### Add constraints
You can use `Class.Constraint|Constraints` to restrict how joints can move when reaching its target. Constraints can ensure joints like the elbows and knees bend naturally, or to make the mechanical joints rotate in a specific orientation.
<GridContainer numColumns="2">
<figure>
<img src="../assets/animation/inverse-kinematics/elbow-unnatural-pose.png"/>
<figcaption>Elbow bending unnaturally</figcaption>
</figure>
<figure>
<img src="../assets/animation/inverse-kinematics/elbow-natural-pose.png"/>
<figcaption>Elbow bending correctly</figcaption>
</figure>
</GridContainer>
To add constraints to your character using `Class.IKControl`, your `Class.IKControl` and constraint must meet the following conditions:
- The attachments referenced in the constraint's `Class.Constraint.Attachment0|Attachment0`/`Class.Constraint.Attachment1|Attachment1` properties attaches to the same parts as the `Class.Motor6D` `Class.Motor6D.Part0|Part0`/`Class.Motor6D.Part1|Part1`.
- The relative positions of `Class.Constraint.Attachment0|Attachment0`/`Class.Constraint.Attachment1|Attachment1` must equal the corresponding positions of the `Class.Motor6D` `Class.Motor6D.C0|C0`/`Class.Motor6D.C1|C1` CFrames.
- The constraint and the IKControl share the same parent `Class.Model`.
The following instructions describe the process of adding a `Class.HingeConstraint` to restrict the rotation of a character's elbow and adding a `Class.BallSocketConstraint` to the wrist to limit the rotation angle.
#### Elbow
Roblox R15 characters already include attachments in their joints that you can use to apply the elbow constraint. For the elbow, both the LeftUpperArm and the LeftLowerArm include a `LeftElbowRigAttachment`. Along with adding a constraint, you also need to add additional child attachments to each part's `LeftElbowRigAttachment` to specify which axis the elbow can rotate about.
To add the `Class.HingeConstraint` and child attachments:
1. In the **Explorer**, locate your model's **LeftLowerArm** and click the **⊕ button**.
2. Add a **HingeConstraint** with the name `LeftElbowConstraint`.
3. In the **Explorer**, navigate to the **LeftUpperArm.LeftElbowRigAttachment** and add an attachment:
1. Click the **⊕ button** to add an **Attachment** with the name `LeftElbowConstraintAttachment0`.
2. In the viewport, select the attachment and use the **Rotate tool** to rotate the attachment so the yellow **PrimaryAxis** is the axis of your elbow's expected rotation.
<img src="../assets/animation/inverse-kinematics/elbow-primary-axis.png" width = "40%"/>
3. Set the **LeftElbowConstraint.Attachment0** property to this new attachment.
4. In the **Explorer**, navigate to your model's **LeftLowerArm.LeftElbowRigAttachment** add an attachment:
1. Click the **⊕ button** and add an **Attachment** with the name `LeftElbowConstraintAttachment1`.
2. Set the **LeftUpperArm.LeftElbowConstraint.Attachment1** property to this new attachment.
3. Copy the **LeftElbowConstraintAttachment0.CFrameOrientation** property and paste it as the **LeftElbowConstraint.Attachment1.CFrameOrientation** value.
<img src="../assets/animation/inverse-kinematics/elbow-natural-pose.png"/>
<Alert severity = 'error'>
If you see a red arrow on the constraint's visualization, that means your attachment orientations are violating the hinge constraint. Go back and make sure the **LeftElbowConstraintAttachment1** has the same orientation as the **LeftElbowConstraintAttachment0**.
</Alert>
Test your IKControl to verify the elbow only rotates about its hinge axis:
<video controls src="../assets/animation/inverse-kinematics/hinge-constraint.mp4" width="100%"></video>
#### Wrists
Even with the elbow constraint, the IKControl can still produce unrealistic poses with the wrists.
<figure>
<img src="../assets/animation/inverse-kinematics/wrist-unnatural-pose.png" width = "40%"/>
<figcaption>The wrist bends unnaturally at certain orientations</figcaption>
</figure>
You can improve this by adding a `Class.BallSocketConstraint` to limit the rotation of the wrist. While this is similar to the process for adding a `Class.HingeConstraint` to the elbow, you can use the `Class.BallSocketConstraint.LimitsEnabled|LimitsEnabled` property on this constraint to further control the range of motion of the wrist.
To add a `Class.BallSocketConstraint` for the wrist:
1. In the **Explorer**, locate your model's **LeftHand** and click the **⊕ button**.
1. Add a **BallSocketConstraint** with the name `LeftWristConstraint`.
2. Locate your model's **LeftLowerArm.LeftWristRigAttachment** and add an attachment:
1. Click the **⊕ button** and add an **Attachment** with the name `LeftWristConstraintAttachment0`.
2. In the viewport, select the attachment and use the **Rotate tool** to rotate the attachment so the yellow PrimaryAxis points toward the model's fingertips.
<img src="../assets/animation/inverse-kinematics/wrist-primary-axis.png" width = "40%"/>
3. Set the **LeftWristConstraint.Attachment0** property to the new `LeftWristConstraintAttachment0`.
3. Locate your model's **LeftHand.LeftWristRigAttachment** and add an attachment:
1. Click the **⊕ button** and add an **Attachment** with the name `LeftWristConstraintAttachment1`.
2. Copy the **LeftWristConstraintAttachment0.CFrameOrientation** property and paste it as the **LeftWristConstraintAttachment1.CFrameOrientation** property.
3. Set the **LeftWristConstraint.Attachment1** property to this new **LeftWristConstraintAttachment1**.
4. In the **Explorer**, select the **LeftWristConstraint**.
5. In the **Properties** window, set the following:
1. Enable **LimitsEnabled**.
2. Set **UpperAngle** to `80`. This controls how much the constraint's axis can rotate, and 80 degrees is approximately how much the wrist should be able to bend.
6. Depending on your character you may want to tweak the direction the cone is pointing in. You can do this by using the **Rotate tool** to rotate the constraint's **Attachment0**.
When selecting the **LeftWristConstraint**, a green cone appears visualizing the wrist's range of motion.
<img src="../assets/animation/inverse-kinematics/wrist-cone.png" width = "40%"/>
With the constraint set up, test the IKControl with the hand pointing down in front of the character and the wrist should rotate and bend more realistically.
<video controls src="../assets/animation/inverse-kinematics/ball-socket-constraint.mp4" width="100%"></video>

View file

@ -0,0 +1,538 @@
---
title: Use animations
description: Explains the process of playing animations through scripts, and replacing default animations.
---
Once you have [created an animation](../animation/editor.md), you need to use scripts to include them in your experience. You can either [play animations manually](#play-animations-from-scripts) from scripts or [replace default animations](#replace-default-animations) for player characters.
## Play animations from scripts
In some cases, you'll need to play an animation directly from inside a script, such as when a user presses a certain key or picks up a special item.
### Humanoids
To play an animation on a rig containing a `Class.Humanoid`
object, such as typical playable characters, follow this basic pattern:
1. Ensure that the local player's `Class.Humanoid` contains an `Class.Animator` object.
2. Create a new `Class.Animation` instance with the proper `Class.Animation.AnimationId|AnimationId`.
3. Load the animation via `Class.Animator:LoadAnimation()` to create an `Class.AnimationTrack`.
4. Play the track with `Class.AnimationTrack:Play()`.
For example, the following `Class.LocalScript`, when placed in
`Class.StarterPlayerScripts`, loads a "kick" animation onto the player's character and plays it. The script also utilizes the `Class.AnimationTrack:GetMarkerReachedSignal()|GetMarkerReachedSignal()` method to detect when a specific [animation event](../animation/events.md) occurs.
```lua title="LocalScript - Play Custom Animation on Player Character"
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
-- Ensure that the character's humanoid contains an "Animator" object
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
-- Create a new "Animation" instance and assign an animation asset ID
local kickAnimation = Instance.new("Animation")
kickAnimation.AnimationId = "rbxassetid://2515090838"
-- Load the animation onto the animator
local kickAnimationTrack = animator:LoadAnimation(kickAnimation)
-- If a named event was defined for the animation, connect it to "GetMarkerReachedSignal()"
kickAnimationTrack:GetMarkerReachedSignal("KickEnd"):Connect(function(paramString)
print(paramString)
end)
task.wait(4)
-- Play the animation track
kickAnimationTrack:Play()
```
### Non-humanoids
To play animations on rigs that do **not** contain a `Class.Humanoid`, you must create an `Class.AnimationController` with a child `Class.Animator`. For example, the following `Class.Script` (assumed to be a direct child of the rig) loads a "kick" animation and plays it.
```lua title="Script - Play Custom Animation on Character Rig"
local rig = script.Parent
-- Create a new "Animation" instance and assign an animation asset ID
local kickAnimation = Instance.new("Animation")
kickAnimation.AnimationId = "rbxassetid://2515090838"
-- Create a new "AnimationController" and "Animator"
local animationController = Instance.new("AnimationController")
animationController.Parent = rig
local animator = Instance.new("Animator")
animator.Parent = animationController
-- Load the animation onto the animator
local kickAnimationTrack = animator:LoadAnimation(kickAnimation)
-- If a named event was defined for the animation, connect it to "GetMarkerReachedSignal()"
kickAnimationTrack:GetMarkerReachedSignal("KickEnd"):Connect(function(paramString)
print(paramString)
end)
task.wait(4)
-- Play the animation track
kickAnimationTrack:Play()
```
## Replace default animations
By default, Roblox player characters include common animations like running,
climbing, swimming, and jumping. You can replace these [default animations](#default-character-animations) with animations from the [catalog](#catalog-animations) or with your own [custom](../animation/editor.md) animations.
1. Obtain the **asset ID** of the new animation as follows:
- For a custom animation built with the [Animation Editor](../animation/editor.md), follow the [export](../animation/editor.md#exporting-an-animation) instructions.
- Copy an appropriate ID from the [catalog animation reference](#catalog-animations) below. For example, to replace the default run animation with the <a href="https://www.roblox.com/catalog/658830056/Ninja-Run" target="_blank" rel="noopener">Ninja&nbsp;Run</a> variant, use `656118852`.
2. In the [Explorer](../studio/explorer.md) window, add a new `Class.Script` to **ServerScriptService**.
1. Hover over **ServerScriptService** and click the &CirclePlus; button.
2. From the contextual menu, insert a **Script**.
3. In the new script, paste the following code:
```lua title="Script - Replace Default Character Animations"
local Players = game:GetService("Players")
local function onCharacterAdded(character)
-- Get animator on humanoid
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
-- Stop all animation tracks
for _, playingTrack in animator:GetPlayingAnimationTracks() do
playingTrack:Stop(0)
end
local animateScript = character:WaitForChild("Animate")
--animateScript.run.RunAnim.AnimationId = "rbxassetid://"
--animateScript.walk.WalkAnim.AnimationId = "rbxassetid://"
--animateScript.jump.JumpAnim.AnimationId = "rbxassetid://"
--animateScript.idle.Animation1.AnimationId = "rbxassetid://"
--animateScript.idle.Animation2.AnimationId = "rbxassetid://"
--animateScript.fall.FallAnim.AnimationId = "rbxassetid://"
--animateScript.swim.Swim.AnimationId = "rbxassetid://"
--animateScript.swimidle.SwimIdle.AnimationId = "rbxassetid://"
--animateScript.climb.ClimbAnim.AnimationId = "rbxassetid://"
end
local function onPlayerAdded(player)
player.CharacterAppearanceLoaded:Connect(onCharacterAdded)
end
Players.PlayerAdded:Connect(onPlayerAdded)
```
4. For each line that references a [default character animation](#default-character-animations), uncomment it and paste the replacement ID after `rbxassetid://`. For example, to change the default run animation to the <a href="https://www.roblox.com/catalog/658830056/Ninja-Run" target="_blank" rel="noopener">Ninja&nbsp;Run</a> variant:
```lua title="Script - Replace Default Character Animations" highlight="14"
local Players = game:GetService("Players")
local function onCharacterAdded(character)
-- Get animator on humanoid
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
-- Stop all animation tracks
for _, playingTrack in animator:GetPlayingAnimationTracks() do
playingTrack:Stop(0)
end
local animateScript = character:WaitForChild("Animate")
animateScript.run.RunAnim.AnimationId = "rbxassetid://656118852"
--animateScript.walk.WalkAnim.AnimationId = "rbxassetid://"
--animateScript.jump.JumpAnim.AnimationId = "rbxassetid://"
--animateScript.idle.Animation1.AnimationId = "rbxassetid://"
--animateScript.idle.Animation2.AnimationId = "rbxassetid://"
--animateScript.fall.FallAnim.AnimationId = "rbxassetid://"
--animateScript.swim.Swim.AnimationId = "rbxassetid://"
--animateScript.swimidle.SwimIdle.AnimationId = "rbxassetid://"
--animateScript.climb.ClimbAnim.AnimationId = "rbxassetid://"
end
local function onPlayerAdded(player)
player.CharacterAppearanceLoaded:Connect(onCharacterAdded)
end
Players.PlayerAdded:Connect(onPlayerAdded)
```
## Set animation weights
You can use multiple animations for the same action. For example, there
are two `idle` variations in the code sample for [replacing default animations](#replace-default-animations).
When multiple animations exist for a character state, the **Animate** script
randomly chooses which one to play, but you can influence the outcome by
setting the animation's `Weight` value under the following formula:
- **animation weight / total weight of all state animations**
In the following example, `idle.Animation1` will play ⅓ of the time the character is idle, while `idle.Animation2` will play ⅔ of the time.
```lua title="Script - Replace Default Character Animations" highlight="3,4"
animateScript.idle.Animation1.AnimationId = "rbxassetid://656117400"
animateScript.idle.Animation2.AnimationId = "rbxassetid://656118341"
animateScript.idle.Animation1.Weight.Value = 5
animateScript.idle.Animation2.Weight.Value = 10
```
## Animation references
### Default character animations
The following table contains all of the default character animations that you can [replace](#replace-default-animations) with [catalog](#catalog-animations) animations or your own [custom](../animation/editor.md) animations. Note that **Idle** has two variations which you can [weight](#set-animation-weights) to play more or less frequently.
<table>
<tbody>
<tr>
<th>Character action</th>
<th>Animate script reference</th>
</tr>
<tr>
<td>**Run**</td>
<td>`animateScript.run.RunAnim.AnimationId`</td>
</tr>
<tr>
<td>**Walk**</td>
<td>`animateScript.walk.WalkAnim.AnimationId`</td>
</tr>
<tr>
<td>**Jump**</td>
<td>`animateScript.jump.JumpAnim.AnimationId`</td>
</tr>
<tr>
<td>**Idle**</td>
<td>
`animateScript.idle.Animation1.AnimationId`<br />
`animateScript.idle.Animation2.AnimationId`
</td>
</tr>
<tr>
<td>**Fall**</td>
<td>`animateScript.fall.FallAnim.AnimationId`</td>
</tr>
<tr>
<td>**Swim**</td>
<td>
`animateScript.swim.Swim.AnimationId`
</td>
</tr>
<tr>
<td>**Swim (Idle)**</td>
<td>
`animateScript.swimidle.SwimIdle.AnimationId`
</td>
</tr>
<tr>
<td>**Climb**</td>
<td>`animateScript.climb.ClimbAnim.AnimationId`</td>
</tr>
</tbody>
</table>
### Catalog animations
When using avatar animation bundles to [replace default animations](#replace-default-animations), use the following references for the respective asset IDs. For example, if you want to apply the <a href="https://www.roblox.com/catalog/658832070/Ninja-Jump" target="_blank" rel="noopener">Ninja&nbsp;Jump</a> animation, use `656117878`. Note that **Idle** has multiple variations.
<table>
<tbody>
<tr>
<td>
<a href="https://www.roblox.com/bundles/34/Astronaut-Animation-Pack" target="_blank" rel="noopener">**Astronaut**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />891636393</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />891636393</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />891627522</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />891621366, 891633237, 1047759695</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />891617961</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />891639666</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />891663592</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />891609353</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/39/Bubbly-Animation-Package" target="_blank" rel="noopener">**Bubbly**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />910025107</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />910034870</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />910016857</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />910004836, 910009958, 1018536639</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />910001910</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />910028158</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />910030921</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />909997997</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/56/Cartoony-Animation-Package" target="_blank" rel="noopener">**Cartoony**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />742638842</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />742640026</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />742637942</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />742637544, 742638445, 885477856</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />742637151</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />742639220</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />742639812</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />742636889</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/48/Elder-Animation-Package" target="_blank" rel="noopener">**Elder**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />845386501</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />845403856</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />845398858</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />845397899, 845400520, 901160519</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />845396048</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />845401742</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />845403127</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />845392038</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/68/Knight-Animation-Package" target="_blank" rel="noopener">**Knight**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />657564596</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />657552124</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />658409194</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />657595757, 657568135, 885499184</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />657600338</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />657560551</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />657557095</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />658360781</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/79/Levitation-Animation-Pack" target="_blank" rel="noopener">**Levitation**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />616010382</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />616013216</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />616008936</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />616006778, 616008087, 886862142</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />616005863</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />616011509</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />616012453</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />616003713</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/63/Mage-Animation-Package" target="_blank" rel="noopener">**Mage**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />707861613</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />707897309</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />707853694</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />707742142, 707855907, 885508740</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />707829716</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />707876443</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />707894699</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />707826056</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/75/Ninja-Animation-Package" target="_blank" rel="noopener">**Ninja**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />656118852</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />656121766</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />656117878</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />656117400, 656118341, 886742569</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />656115606</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />656119721</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />656121397</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />656114359</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/55/Pirate-Animation-Package" target="_blank" rel="noopener">**Pirate**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />750783738</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />750785693</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />750782230</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />750781874, 750782770, 885515365</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />750780242</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />750784579</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />750785176</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />750779899</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/82/Robot-Animation-Pack" target="_blank" rel="noopener">**Robot**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />616091570</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />616095330</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />616090535</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />616088211, 616089559, 885531463</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />616087089</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />616092998</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />616094091</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />616086039</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/356/Rthro-Animation-Package" target="_blank" rel="noopener">**Rthro**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />2510198475</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />2510202577</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />2510197830</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />2510197257, 2510196951, 3711062489</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />2510195892</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />2510199791</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />2510201162</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />2510192778</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/83/Stylish-Animation-Pack" target="_blank" rel="noopener">**Stylish**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />616140816</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />616146177</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />616139451</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />616136790, 616138447, 886888594</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />616134815</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />616143378</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />616144772</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />616133594</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/81/Superhero-Animation-Pack" target="_blank" rel="noopener">**Superhero**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />616117076</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />616122287</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />616115533</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />616111295, 616113536, 885535855</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />616108001</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />616119360</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />616120861</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />616104706</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/43/Toy-Animation-Pack" target="_blank" rel="noopener">**Toy**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />782842708</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />782843345</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />782847020</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />782841498, 782845736, 980952228</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />782846423</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />782844582</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />782845186</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />782843869</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/33/Vampire-Animation-Pack" target="_blank" rel="noopener">**Vampire**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />1083462077</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />1083473930</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />1083455352</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />1083445855, 1083450166, 1088037547</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />1083443587</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />1083464683</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />1083467779</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />1083439238</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/32/Werewolf-Animation-Pack" target="_blank" rel="noopener">**Werewolf**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />1083216690</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />1083178339</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />1083218792</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />1083195517, 1083214717, 1099492820</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />1083189019</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />1083222527</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />1083225406</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />1083182000</Grid>
</Grid>
</td>
</tr>
<tr>
<td>
<a href="https://www.roblox.com/bundles/80/Zombie-Animation-Pack" target="_blank" rel="noopener">**Zombie**</a>
</td>
<td>
<Grid container spacing={1}>
<Grid item XSmall={4} XLarge={2}>**Run**<br />616163682</Grid>
<Grid item XSmall={4} XLarge={2}>**Walk**<br />616168032</Grid>
<Grid item XSmall={4} XLarge={2}>**Jump**<br />616161997</Grid>
<Grid item XSmall={12} XLarge={6}>**Idle**<br />616158929, 616160636, 885545458</Grid>
<Grid item XSmall={4} XLarge={2}>**Fall**<br />616157476</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim**<br />616165109</Grid>
<Grid item XSmall={4} XLarge={2}>**Swim (Idle)**<br />616166655</Grid>
<Grid item XSmall={4} XLarge={2}>**Climb**<br />616156119</Grid>
</Grid>
</td>
</tr>
</tbody>
</table>