About this mod
A custom animation system for Starfield that can load and play GLTF animations.
- Requirements
- Permissions and credits
- Changelogs

NAF adds a fully custom animation system to Starfield that can load and play the widely-supported GLTF animation format.
Requirements
Starfield Script Extender
Address Library for SFSE Plugins
Highly Recommended
Trainwreck Crash Logger
Trainwreck provides a lot of useful information if the game crashes. If you get a crash while using NAF, please post the crash log in the Bugs section with information on what you were doing before the crash occured, as well as any other mods you have installed.
How to Use
Creating Animations in Blender
Note #1: Steps 1 to 7 can be skipped if you download the Blender Scene file in the optional downloads.
Note #2: By default, NAF only comes with support for the Human skeleton. For information on adding other skeletons, see the "Adding Non-Human Skeletons" section.
1.) Download this fork of NifSkope that has been updated to the latest Starfield patch: https://github.com/fo76utils/nifskope/releases (Ensure you have the Starfield Data folder properly configured in Options->Settings so it can find meshes.)
2.) Open two NifSkope windows, one with the skeleton.nif and the other with the body .nif
3.) In the body .nif, right click on the BSGeometry node and select Block->Copy Branch
4.) In the skeleton.nif, right click on the NiNode named "Root" and select Block->Paste Branch
5.) Repeat for the head, eyes, and hand models, pasting them all into the one skeleton.nif scene
6.) Select the root NiNode in skeleton.nif and then at the top of the window select File->Export->Export .glTF
7.) Import the .glTF into Blender. Important: On the import window, make sure Bone Dir is set to Blender, and Guess Original Bind Pose is not selected.
8.) Make sure you are in pose mode and animate the skeleton any way you'd like. There's nothing special to Starfield about this step, just normal Blender animation. There's a ton of videos on YouTube that explain how to animate in Blender in-depth.
9.) When you're ready to export your animation, right-click on the skeleton's Root node and choose Select Hierarchy. Then, go to File -> Export -> glTF 2.0. (Make sure to un-select any geometry, otherwise that geometry will get saved to the glTF file, making the file size much bigger than it needs to be.)


10.) Copy the export settings in the images below. Both the .gltf and .glb formats are supported. The "Group by NLA Track" setting depends on how you made your animation. But if you're not sure what it means, leave it disabled. Optimize Animation Size can also be enabled, depending on preference.




10.) Save the file somewhere in the Starfield/Data/NAF folder.
Playing Animations In-Game
NAF currently has three methods of starting animations in-game - with console commands, with Papyrus, or through the cross-plugin API.
Console Commands:
naf play <file_path> <optional: actor_form_id>
Plays a .gltf/.glb animation on the selected actor, looping until stopped. The file path is starting from the Starfield/Data/NAF folder.i.e. if you have an animation at Starfield/Data/NAF/MyCoolAnimation.gltf, you would just enter MyCoolAnimation.gltf as the file path.
naf stop <optional: actor_form_id>
Stops any .gltf/.glb animations currently playing on the selected actor.naf sync <actor_form_id> <actor_form_id> <any # more...>
Synchronizes a set of actors to one another. Only works if the actors are playing a NAF animation.Details:
- Internally, the sync command attaches a SyncInstance to actors. They can either be the owner of the SyncInstance, or a member. Members will synchronize to the owner's animation time and root position.
- The first actor specified in the sync command will be marked as the owner. The other actors specified will be members.
- It's possible to make actors join an existing SyncInstance. Take the following example: A1(owner), A2, A3 are in a SyncInstance. If you then run the command 'naf sync A2 A4 A5', then the SyncInstance will change to be the following: A1, A2(owner), A3, A4, A5.
- Actors will leave a SyncInstance if the stop or stopsync command is ran on them. If the owner leaves the instance, then all members will be forced to leave the instance as well.
naf stopsync <optional: actor_form_id>
Makes the selected actor leave their current SyncInstance, if they're in one.
naf optimize <file_path> <optional: actor_form_id>
Optimizes a .gltf/.glb animation's file size, using the selected actor's skeleton. This will remove all non-animation data from the file & apply a lossless compression algorithm. Make sure to backup the file first. This process optimizes the file specifically for NAF, it might not work with other programs after running this command. The file path is starting from the Starfield/Data/NAF folder, same as the play and playk commands.
naf playk <file_path> <optional: actor_form_id>
Functions the same as the play command, but enables up arrow/down arrow hotkeys for quickly scrolling through installed animations. The hotkeys will only affect the latest actor that this command was ran on. (The hotkeys will be disabled again when the 'stop' command is ran on the same actor.)
Papyrus API:
The Papyrus API is available via the NAF global script included in the download. It is currently just a wrapper around the console commands.
PlayAnimation(Actor akTarget, String asAnim): Functions the same as the play command.
StopAnimation(Actor akTarget): Functions the same as the stop command.
SyncAnimations(Actor[] akTargets): Functions the same as the sync command.
StopSyncing(Actor akTarget): Functions the same as the stopsync command.
Cross-Plugin API:
If you are an SFSE plugin developer and would like to start NAF animations from your plugin, you can copy the API header available here into your project. The API automatically finds NAF's exported functions, so all you have to do is call them. Note: Make sure to not call any NAF API functions before the kPostLoad SFSE event, as the NAF dll might not be loaded before that point.
Adding Non-Human Skeletons/Extending Skeletons
NAF maps skeletons by race. You might've noticed that NAF comes with a HumanRace.json file in the Starfield/Data/NAF/Skeletons folder. This file lists out all of the nodes in the Human skeleton that animations can map to. The nodes don't need to be in any particular order, and if someone releases an extended skeleton, you can just add the node names here.
To add support for other races, copy the HumanRace.json file and rename it to the editor ID of the race you want to support (editor IDs can be viewed in xEdit). Then inside the new file, replace the list of nodes with the names of the nodes for the new race's skeleton. To find the names of the nodes, extract skeleton.nif for the corresponding race from the game's "Meshes" .ba2 files and open it in NifSkope. Starting from the Root node, all the names of the attached nodes are what you need. Once you've got them listed out, save the file and restart the game. NAF will automatically recognize the skeleton information.
- More API functions.
- Co-save serialization once that becomes available in SFSE.
-
-
-
NAF's animation system runs on top of the game's normal animation system. This means it can't replace vanilla animations, but it can override them if a NAF animation is started at the same time. Also, since SFSE doesn't have co-save serialization yet, NAF isn't able to remember which animations are playing between game sessions. If a NAF animation is playing and you save the game, that animation won't be playing when you reload that save.
Credits
Big thanks to maximusmaxy for sharing their Starfield RE findings.
meh321 for Address Library for SFSE Plugins.
Ian Patterson for Starfield Script Extender.
Links