Animations - BadDogSkyrim/PyNifly GitHub Wiki

Support for animation HKX files is complete for Skyrim LE only, though additional features and extensions can be expected. It would be very helpful to me if folks would import animations they work with and let me know if their are problems.

Animations embedded in the nifs work for all examples I've found.

Video tutorial covering basic functionality here.

Import

Animations in nif files

Some nifs are animated: chests and doors that open and close, flags that wave, and so forth. These animations are embedded in the nif file with the mesh.

  • An animation in the nif is represented as a single Action in Blender with Action Slots for each element. There may be fewer Action Slots in Blender than Controlled Blocks in the nif because an Action Slot can affect multiple properties through different fcurves.

  • There may be multiple named animations in the nif ("open"/"close" on a chest, for example). Each animation can affect multiple objects, for example the Dwemer chest which has multiple gears and levers. There will only be one Action but in order to see it work (to switch from "open" to "close" animations), you have to set the action and the slot correctly on every affected element.

  • To make it easier to apply an animation, there's a routine to help. F3 -> "Apply Nif Animation" -> Choose the one you want.

  • Actions implementing a named animation are marked as assets and given the "fake user" flag so you can find them later and so they won't disappear. The action name is the name of the animation in the nif file if it has one, otherwise it's usually the name of the thing animated.

  • Animated clutter often has the animation on a node which is the parent of the TriShape mesh. Sometimes it's the parent of several meshes. These will be empties in your import, the animation will be attached to them, and they'll move all their children together.

Under the hood

  • An element (object or material node tree) to be animated with a named animation must have the "pynActionSlots" property set to a value like "Open|Object003||Close|Object003". This indicates when the "Open" Action is applied to it, it should get Action Slot "Object003". That's because one Action can have an Action Slot which makes a gear turn and another which makes a door slide, and the Action Slots can be applied to anything. Object003 has to get (say) the turning Action Slot, not the sliding Action Slot. This is handled for you on import. If you're building animations from scratch, you have to know about it.

  • If you want an Action to be exported as a Controller Sequence handled by a Controller Manager, it must have the custom property "pynController" set to "NiControllerSequence". This is necessary so that we don't export Controller Managers when they aren't necessary.

Animation files

  • Character animation files (HKX or KF files) need an armature for import. Import the nif skeleton first, typically with "Create Bones" off and "Rename Bones" on. Import any body parts you like. Then, with the skeleton selected, import the animation. Any bones that are affected by the animation but not in your armature will be ignored, so check the console. Such animations will be fine, but on export those bones will be missing and that may be a problem.

  • Animation files also need an HKX skeleton for import, because the animation file itself has no skeleton information. Provide the skeleton.hkx file for people, or the equivalent for other types of actors. (In the future we may obviate this step.)

  • You can, for example, import a body, select the armature, and import an animation. The body will be animated with the armature. Or you can import a skeleton, import a body with the armature selected, then import an animation. You'll get the same result but with a full skeleton. There may be magic nodes or camera nodes associated with the animation which the body doesn't have, so the first option is generally better.

  • Animations may have text annotations at specific time signatures, which are used for things like synchronizing a footstep with the foot visibly landing on the ground. Text annotations appear as markers. Markers are associated with the with the Action. You may need to make them visible with View -> Show Markers in one on the animation panes.

General

  • Blender's FPS setting controls how many frames you get in the resulting animation. If the animation runs 10 seconds and you have the default 24 FPS, you'll get 240 frames. I recommend increasing the FPS to 60 or so for smoother animations. Do this before importing.

Export

  • On export, ALL named animations in the file will be exported, whether active or not, if they affect any object being exported.

  • Animated meshes are exported at the position and with the values of the first frame of the currently active animation. If you don't want that, remove it before export.

  • For character animations, select the animated armature and export. You may need to provide a skeleton.hkx file, but if you imported to this armature the skeleton file you used will be remembered.

  • The animation will be exported at 30 fps by default. You can change the number if you like. You can probably blow up the system that way.

Skeleton files

There are HKX skeleton files, which need to be generated if you want to add auxbones for your animation. pyNifly currently supports generating these files (as XML files). Go into pose mode, select the bones of your armature that you want to include, and export "Skeleton file (XML)". This will generate an XML file which you can put through hkxcmd to make the HKX file.

Animation Structure

Notes on how animations are structured in the nif. You should not need this info to import and export animations.

Animated objects

These are objects like chests that have animations that can be triggered by the game, but which are not skinned.

  • If there are multiple named animations, the root has a controller, a NiControllerManager. But the Controller Manager doesn't control anything directly, not even the root. Instead it parents one or more Controller Sequences.

  • NiControllerSequence blocks are the individual named animations. The name allows them to be triggered by the game--e.g. the chest has one named "Open" and another "Close".

  • NiControllerSequence contains one or more Controlled Block structures. Each defines one target that is controlled and references an interpolator and a controller. (Usually. Sometimes one or the other is missing.) The target may be a node or may be some other element, like a shader.

  • The interpolator references a Data block, which holds the individual keyframes and values.

  • The Data block does the real work of animating one node. Animations consist of what Blender calls fcurves, the path any property of the node takes through time. For transforms, that's translation, rotation, and scale--but it can be color, U/V offset, or other properties.

HKX Animation Files

Animations are handled through KF files (which are just a type of nif file). HKXCMD is used to transform between HKX and KF format. HKXCMD is also used to go between HKX and XML files, which lets us add information to the animation that KF doesn't support. None of this is directly visible, though you'll see notifications in the console showing the names of generated temporary files.

The flow is:

  • Import: HKX -> KF + XML; KF + XML -> Blender. The XML captures text annotations that get lost in the KF format.

  • Export: Blender -> KF -> HKX -> XML; extend the XML with annotations; XML -> HKX.

  • KF files have a NiControllerSequence as the root node. That has a Controlled Block for every bone that gets animated.


Necessary files to create for full animation support:

Project file: XML -> HKX. pyNifly won't do this--there are other tools.

Character file: XML -> HKX. pyNifly won't do.

Behavior file: XML -> HKX. PyNifly won't do.

Skeleton file: XML -> HKX. pyNifly now supports generating the XML.