Skip to content

Commit

Permalink
Skeletal animation improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
jankrassnigg committed Nov 4, 2023
1 parent bb92f26 commit 03ea08f
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 14 deletions.
Binary file modified pages/docs/animation/media/skeletal-anim.webm
Binary file not shown.
Binary file modified pages/docs/animation/media/skeleton-asset.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ An animation clip represents a single motion, such as a walk cycle, a jump or ot

* `FirstFrame`, `NumFrames`: It is best to put every animation into a separate clip and export them that way. However, sometimes files contain only a single animation and each clip is found at another interval. By specifying the index of the first frame and the number of frames to use, you can extract individual clips from such data. Note that setting NumFrames to zero always means to use all the remaining frames after the first frame.

**Note:** It can be difficult to know the exact indices. Sometimes the data is authored at 24 frame per second and also exported that way, then you can plug in the numbers straight away. However, GLTF/GLB files are always exported at 1000 FPS. That means if your animation clip was authored with 24 FPS and starts at the one second mark, in the GLB file this wouldn't be at keyframe 24, but at keyframe 1000.
**Note:** It can be difficult to know the exact indices. Sometimes the data is authored at 24 frames per second and also exported that way, then you can plug in the numbers straight away. However, GLTF/GLB files are always exported at 1000 FPS. That means if your animation clip was authored with 24 FPS and starts at the one second mark, in the GLB file this wouldn't be at keyframe 24, but instead at keyframe 1000.

* `PreviewMesh`: The [animated mesh](animated-mesh-asset.md) to use for previewing this animation clip. This has to be set to see any preview.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

These events can be used for mundane things like *foot down* markers, in a walking animation, to vital gameplay information like *shot fired* in an attack animation.

Whenver the EZ animation system plays back any animation clip, it also inspects all the *event track*. For every event that it encounters, it broadcasts an `ezMsgGenericEvent` with `Message` set to the value of the event's name.
Whenver the EZ animation system plays back any animation clip, it also inspects the *event track*. For every event that it encounters, it broadcasts an `ezMsgGenericEvent` with `Message` set to the value of the event's name.

If you have a [TypeScript](../../custom-code/typescript/typescript-overview.md) or [Visual Script](../../custom-code/visual-script/visual-script-overview.md) (or [custom C++ components](../../custom-code/cpp/custom-cpp-component.md) that is also an event handler) attached to any parent node of the animated mesh, you can handle this type of event and react with the desired game logic.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The *joint attachment component* is used to expose the animated position of a bo

<video src="../media/anim-point-shoot.webm" width="800" height="600" autoplay loop></video>

In the video above a joint override component was used to expose the position of the right hand as a game object. This was then used as the parent object for a gun object.
In the video above a joint attachment component was used to expose the position of the right hand as a game object. This was then used as the parent object for a gun object.

## Component Properties

Expand Down
6 changes: 3 additions & 3 deletions pages/docs/animation/skeletal-animation/root-motion.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

By default a skeletal animation has its origin at the position of the game object on which it is played. Relative to that location animations will move the bones and the skinned mesh will move accordingly. The game object itself stays fixed at that location, though.

This is sufficient if either the game object shouldn't change its location anyway, or when any change in position is controlled through other means anyway. For example a player character might be moved around the world through [custom code](../../custom-code/custom-code-overview.md) and a walking animation is only played to visualize the action. This approach can be the right solution, depending on the type of game.
This is sufficient if either the game object shouldn't change its location anyway, or when any change in position is controlled through other means. For example a player character might be moved around the world through [custom code](../../custom-code/custom-code-overview.md) and a walking animation is only played to visualize the action. This approach can be the right solution, depending on the type of game.

Such a method is, however, very prone to *foot sliding*, meaning an artifact where the feet move, but don't *stick* to the ground. It the movement of a game object should generally be determined by the exact blend of animation clips, it is better to have the motion be part of each animation clip.
Such a method is, however, very prone to *foot sliding*, meaning an artifact where the feet move, but don't *stick* to the ground. If the movement of a game object should generally be determined by the exact blend of animation clips, it is better to have the motion be part of each animation clip.

For example a *walk animations* would contain the information into which direction and at what speed a game object should be moved to fit the animation. When a *forward* and *walk right* animation get mixed together, their root motion information is equally mixed and the object would be moved diagonally.
For example a *walk animation* would contain the information into which direction and at what speed a game object should be moved to fit the animation. When a *forward* and *walk right* animation get mixed together, their root motion information is equally mixed and the object would be moved diagonally.

## Defining Root Motion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ For more complex scenarios use an [animation controller](animation-controller/an

* `RootMotionMode`: Selects how [root motion](root-motion.md) is applied to the owning game object.

## Events
* `InvisibleUpdateRate`: How often to update the animation when the object is not visible. For performance reasons the update rate should be very low or even paused when an object isn't visible. However, since animations may have an important impact on gameplay, it can be undesirable to have a lower update rate even when the object is not visible. Note that this affects the update rate of objects that are not visible by the main camera, but by a shadow casting light. Objects whose shadow can be seen generally get updated, but at a low rate, unless this setting forces a higher update rate.

## Animation Events

The component will broadcast the event `ezMsgGenericEvent` every time it encounters an [animation event](animation-events.md) in the animation clip. [Custom code](../../custom-code/custom-code-overview.md) can listen for these events and trigger relevant game mechanics.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The rest of this document gives a high-level overview, how to get started with g

## Sample Scene

For a sample scene to look at, open the **Animation** scene from the [Testing Chambers](../../../samples/testing-chambers.md) project.
For a sample scene to look at, open the **Animation** scene from the [Testing Chambers](../../../samples/testing-chambers.md) project. Additionally, the [Monster Attack Sample](../../../samples/monster-attack/monster-attack.md) may also be a useful resource.

## The Animation System Pieces

Expand All @@ -22,7 +22,7 @@ The [animated mesh](animated-mesh-asset.md) asset represents the mesh of the ani

### Skeleton Asset

The [skeleton asset](skeleton-asset.md) stores the bone hierarchy of the animated object. This is also where you configure the overall scaling and which direction should be the forward, right and up vector of the imported model. The skeleton asset is also where you would set up physics collision shapes.
The [skeleton asset](skeleton-asset.md) stores the bone hierarchy of the animated object. This is also where you configure the overall scaling and which direction should be the forward, right and up vector of the imported model. The skeleton asset is also where you set up physics collision shapes for [hit detection](../../physics/jolt/ragdolls/jolt-hitbox-component.md) and [ragdolls](../../physics/jolt/ragdolls/jolt-ragdoll-component.md).

### Animation Clip Asset

Expand Down Expand Up @@ -60,7 +60,7 @@ To import an animated object, you need to set up multiple assets (the mesh, the

![Animation import](../media/anim-import.png)

This will create all three necessary assets. You can repeat this process, if you want to import multiple animation clips (select *No Import* for the other asset types then). You'll need to change the filename for each additional animation clip asset.
This will create all three necessary assets. To import additional animation clips, the easiest method is to just use *File > Save As...* in the existing animation clip asset to duplicate it for the next clip.

## Animation Utility Components

Expand Down
34 changes: 32 additions & 2 deletions pages/docs/animation/skeletal-animation/skeleton-asset.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
# Skeleton Asset

The main function of the *Skeleton asset* is to store information about the bone hierarchy in an [animated mesh](animated-mesh-asset.md). Here you adjust the overall scale and rotation of imported animated meshes.
The main function of the *Skeleton asset* is to store information about the bone hierarchy in an [animated mesh](animated-mesh-asset.md). It is a central aspect for all [skeletal animations](skeletal-animation-overview.md).

![Skeleton Asset](../media/skeleton-asset.jpg)

In the future the skeleton asset will also be used to define physics shapes for bones for collision detection and ragdolls. This is currently not yet implemented, though.
The skeleton is used to adjust the overall scale and rotation of animated meshes. It is also used to define [collision shapes](../../physics/jolt/collision-shapes/jolt-shapes.md) for bones, which is needed for [hit detection](../../physics/jolt/ragdolls/jolt-hitbox-component.md) and when additionally joint types and joint limits are configured, the skeleton can be used for [ragdolls](../../physics/jolt/ragdolls/jolt-ragdoll-component.md).

## User Interface

The left hand side shows a tree view with the bone hierarchy. The top most element is always the `ezEditableSkeleton` node, which represents the skeleton in general.

When you select any node in this tree, the *Skeleton Properties* panel on the right displays the properties of the selected node. Select the root node (`ezEditableSkeleton`) to edit the overall properties, such as which file to import. Once a file is imported, the bones should show up as child nodes. Select any of them, to configure the properties of a bone.

## Asset Properties

Select the `ezEditableSkeleton` node to edit the overall asset properties.

* `File`: The file from which to import the skeleton information. This is typically the same file as in the [animated mesh asset](animated-mesh-asset.md).

* `RightDir`, `UpDir`, `FlipForwardDir`: These properties are the same as on the [mesh asset](../../graphics/meshes/mesh-asset.md#asset-properties). Depending on how the mesh was exported, you may need to adjust these to have the skeleton (and every mesh that uses this skeleton) stand upright and look into the correct direction.
Expand Down Expand Up @@ -40,6 +48,28 @@ In the future the skeleton asset will also be used to define physics shapes for

* `MaxImpulse`: When projectiles and other things apply impulses to ragdoll limbs, the forces can quickly add up and fling a ragdoll far away. This value is used to clamp the maximum impulse to apply to prevent that.

## Bone Properties

Select a bone from the hierarchy to edit its properties.

> **Note:**
>
> **All** bone properties are *physics properties* that are used for setting up [collision shapes](../../physics/jolt/collision-shapes/jolt-shapes.md) and [constraints](../../physics/jolt/constraints/jolt-constraints.md). Collider shapes are needed for [hit detection](../../physics/jolt/ragdolls/jolt-hitbox-component.md). Colliders and constraints are only needed for [ragdolls](../../physics/jolt/ragdolls/jolt-ragdoll-component.md).
* `Local Rotation`: This property only shows up on bones that have a parent bone with a collision shape. It is used to adjust the orientation of the *joint constraint*.

* `Joint Type`: Selects what kind of constraint should be between this bone and the parent bone. If it is set to `None`, the two bones are not joined. If the skeleton is not meant to be used for ragdolls, there is no reason to select anything else. If the type is set to `Fixed` the two bones are going to be joined such that they are perfectly stiff. In `Swing Twist` mode you can configure the range of motion between these bones to limit how far they can physically move when simulated as a ragdoll.

* `Stiffness`: How easily the ragdoll joint bends.

* `Swing Limit Y/Z`, `Twist Limit`, `Twist Limit Center Angle`: All these are used to set up the swing-twist constraint. Enable the visualization of the constraint limits to see their effect. The swing limit restricts how far a bone may swing away from its parent bone. Be aware that you can only define the swing limit as a *half angle*, meaning it swings both ways. Adjust the `Local Rotation` to define what the *center* of the bone transform is, such that both extremes end up as a natural movement range. The twist limit works similar, it restricts how much the bone may twist around its main axis and the limit goes both ways.Adjust the *center angle* to be somewhere within the current limit range, otherwise the moment ragdoll mode gets activated, the bones will immediately twist to be within the limit, which ends up looking very weird.

* `Override Surface` / `Override Collision Layer`: If either of these is activated, you may specify a different [surface](../../materials/surfaces.md) or [collision layer](../../physics/jolt/collision-shapes/jolt-collision-layers.md) to use just for this bone. Note that the default is configured on the root node.

* `Bone Shapes`: An array of shapes to use for this bone. Use this to configure the approximate physical shape of the mesh, which will be used for hit detection or ragdolls.

* `Colliders`: A mesh may contain custom collider shapes, which can be extracted automatically. For this to work a mesh must use the name prefix `UCX_` to indicate that it is a convex mesh. It must then continue with the bone name to which it should be attached to. So for example, if the bone is called `Bone.001`, and the custom convex mesh is called `UCX_Bone.001` then the mesh will be used as a convex collider shape for that bone. As an example, see the *BreakableCube.glb* file in the t[Testing Chambers](../../../samples/testing-chambers.md) project and the corresponding *BreakableCube* skeleton asset.

## See Also

* [Skeletal Animations](skeletal-animation-overview.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ This component is only meant for debugging purposes.

* `VisualizeSkeleton`: Whether the component should visualize the skeleton at this time.

* `VisualizeColliders`: Whether the collision shapes of the skeleton should be visualized.

* `VisualizeJoints`: Whether the joints between the bones shall be visualized.

* `VisualizeSwingLimits`, `VisualizeTwistLimits`: Whether the swing and twist limits of the joints shall be visualized.

* `BonesToHighlight`: A semicolon-separated list of bone names (case sensitive). Every bone whose name appears in the list will be rendered with a highlight. To know the available bone names, inspect the bone hierarchy in the respective [skeleton asset](skeleton-asset.md).

## See Also


* [Skeletal Animations](skeletal-animation-overview.md)
* [Animated Mesh Component](animated-mesh-component.md)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Skeleton Pose Component

The *skeleton pose component* allows you to assign a custom, static pose to an animated mesh. This can be used for decorative purposes, for instance to place an animated mesh in different poses in your scenes, but it can also be used as a start pose for a mesh that is further animated, for example through [ragdoll physics](../../physics/jolt/ragdolls/jolt-ragdoll-component.md).
The *skeleton pose component* allows you to assign a custom, static pose to an [animated mesh](animated-mesh-component.md). This can be used for decorative purposes, for instance to place an animated mesh in different poses in your scenes, but it can also be used as a start pose for a mesh that is further animated, for example through [ragdoll physics](../../physics/jolt/ragdolls/jolt-ragdoll-component.md).

![Custom pose for animated mesh](media/custom-pose.jpg)

Expand Down

0 comments on commit 03ea08f

Please sign in to comment.