Decoupled animations, as the name suggests, is a way to completely decouple model animations from states. Among the currently supported formats only IQM can utilize this feature.
The advantages of this approach:
- You don't need to define a long list of keyframes in your model. No more FrameIndex, no need to worry about binding keyframes to sprites. All you need is named animation sequences in your model (more on that below).
- You don't have to worry about matching state logic and animation keyframes. These are now independent.
- Decoupled animations can be played with any framerate. You're no longer bound to tics in your animations.
Prerequisites
- ZScript version must be set to "4.12"
- The actor that is going to utilize decoupled animations will need +DECOUPLEDANIMATIONS actor flag.
- The MODELDEF definition for the model will need the BaseFrame property.
- You will need actual named animation sequences built into your model.
I'm using Blender 3.5 with the IQM exporter plugin. Despite being made for an earlier version, it works in 3.5 mostly without issues.
The easiest way to set up named animation sequences in Blender is to use Nonlinear Animation (NLA). If you've never heard of it, take a quick look at the Blender's manual on NLA. Note, using it to create named animation sequences (or, in Blender terms, actions) is not obligatory, but it makes things easier (as does the NLA workflow in general).
Obviously, make sure you have your model and armature set up, since this only works with IQM, which uses skeletal animations.
First, have both Dope Sheet and the Nonlinear Animation tabs open. Nonlinear Animation is selectable among other window types:
Select your bones and create a keyframe as usual:
Your keyframe will appear as usual in the Dope Sheet. Note that it creates a new action with a generated name (the name's default pattern is "<object name>Action", so in my case it's "alice_base_skeletonAction"). At this point you can double-click it and rename it to whatever you want. Also you will see a new action appear in the NLA window (lower part of the screenshot):
Once you've keyframed everything you wanted for this animation sequence, click on the small arrow next to the action name in the NLA tab to turn it into an NLA strip (as show in the screenshot above). This is now an isolated animation sequence that you can drag around your NLA tracks, moving however you want.
You can edit each of those NLA strips at any point. Just click on one and press Tab: the strip will become green, and its contents will open in the Dope Sheet to be edited:
Once you're done editing, press Tab again to close the NLA strip editing.
Important notes
- The names of the NLA strips are NOT the same thing as the names of the actions. In fact, the names of the NLA strips are not relevant at all, they're just for your convenience and they're a Blender thing. They won't be stored in the IQM model in any way. The names of the actions is what matters. They can be seen and changed in the Dope Sheet.
- The placement and order of the NLA strips is irrelevant. Again, this is a Blender thing. For IQM, NLA strips don't exist, only separate, uniquely-named animation sequences do. They're completely isolated from each other.
Export the model!
- Select the meshes
- Shift-select the armature
- File > Export > Inter-Quake Model (.iqm, .iqe)
- Input ALL names of the actions you want to export, separated by a comma:
What to do in ZScript
You will need to use the SetAnimation function. It's documented on the wiki, so I'm not going to delve deep into it. Just some very simple example code:
Code: Select all
Model MyCharacter
{
Path "models/characters"
Model 0 "myplayer.iqm"
BaseFrame //DO NOT FORGET ABOUT THIS
}
Code: Select all
class MyCharacter : PlayerPawn
{
Default
{
+DECOUPLEDANIMATIONS
}
States
{
Spawn:
M000 A -1 NoDelay SetAnimation('idlebreathing', flags:SAF_LOOP);
stop;
See:
M000 A -1 SetAnimation('walking', flags:SAF_LOOP);
stop;
}
}
To do
I will try to add example files to showcase all of the above more clearly later; just wanted to get the information out.