IMPORTANT NOTE: As part of the upcoming FSM overhaul/cleanup, I'm currently in the process of cleaning up a lot of technical debt in this library. Unfortunately as part of this the next release (v0.9.0) will contain some breaking changes to the serialization format. I've been putting off these changes for a while to avoid the churn of breaking existing graphs, but over time enough tech debt has accumulated that it's getting in the way, so it might be time to "rip the baindaid off".
To make migration as painless as possible, I've cut this release (v0.8.0) before any changes to the serialization format, and I'll be publishing a migration guide together with v0.9.0 when that's ready.
Highlights
Ragdoll support using Avian
With the physics_avian feature flag, there's now ragdoll physics integration. This includes:
- Ragdoll editor tab in the editor:
- Support for partial ragdolls, where some bones are "ragdolled"/simulated while others follow the animation pose kinematically.
- Configuration about which bones are simulated/kinematically tracked/ignored is provided via a
RagdollConfigoutput in the graph, so you can change the state of the ragdoll dynamically with animation graph logic.
There's also some limitations however:
- Currently FSMs only support pose outputs, so you cannot use an FSM to determine which
RagdollConfigshould be active. The options if you want dynamically changing ragdoll configs are to define a custom stateful node which outputs aRagdollConfig(seeeditor_as_a_pluginexample) or pass the desired ragdoll config to the graph via graph inputs. - This feature is still experimental of course, please report any bugs you run into!
Custom stateful data
I've done a large refactoring of how both cached outputs and stateful data is stored for animation graph nodes. Besides removing a fair bit of tech debt, this enables support for any node to store custom state through the PassContext, as simply as:
impl NodeLike for SomeNode {
// ...
fn update(&self, mut ctx: PassContext) -> Result<(), GraphError> {
// ...
let state = ctx.state_mut::<StateType>()?;
// or if you need some custom initialization or your state does not implement Default
let state = ctx.state_mut_or_else(|| StateType::default())?;
// ...
}
}The state is stored as a Box<dyn Any>-ish and downcasted on access. This is now the state store backing FSMs, but it also enables many more classes of custom stateful nodes. My favorite application is for blending IK targets, especially:
- In a "look-at" node, you don't want your character to immediately teleport their head towards the new look target. I usually use a heavily dampened spring-mass system to interpolate towards the look target; previously this had to be done outside of the animation graph and the interpolated look direction sent in, but now it can be done directly in an animation node. (I find this node so useful I might add it as a builtin node soon)
- Using an IK target for your character's hand when they're reaching for something.
These are both things that were not well-suited to FSMs, as the "state" is not discrete.
Bevy 0.17 update
Better late than never 😅
Changelog
- fix: workaround Bevy issue #19219 by @mbrea-c in #95
- fix: remove unwrap causing crash by @mbrea-c in #96
- Attaching "hitbox" colliders to bones by @mbrea-c in #97
- fix: hide vec2 plane picker in popup, fix id overlap by @mbrea-c in #98
- feat: improve debug bone rendering by @mbrea-c in #99
- feat: add labels to created colliders by @mbrea-c in #100
- fix: avoid race condition when spawning animated scenes with colliders by @mbrea-c in #101
- fix: add physics plugin if physics feature enable in editor by @mbrea-c in #102
- Ragdoll physics integration with Avian by @mbrea-c in #103
- Update to Bevy 0.17 and avian 0.4 by @mbrea-c in #108
- Make arbitrary state storage available to graph nodes by @mbrea-c in #109
Full Changelog: v0.7.0...v0.8.0