-
Notifications
You must be signed in to change notification settings - Fork 11
Creating Custom Animations
This tutorial covers the full round-trip for making custom animations in Assassin's Creed games: exporting a game .Animation to glTF/GLB, editing it in Blender, and reimporting it as a new animation the game can play.
It builds on two things you should already know:
- The Mesh Viewer and its Blender workflow (see the Mesh Viewer guide) — animations are exported and imported through the same viewer.
- How animations are referenced and swapped (see Lesson 5 – Animations) — once you have a custom animation, that lesson shows how to make a character actually use it.
The single most important rule in this whole tutorial: before you export an animation, load every skeleton the animation uses into the viewer. If you don't, parts of the animation are silently dropped from the export — no error, no warning. The section below explains exactly why.
Currently the Mesh Viewer cannot preview the animations, to find animations and preview them, use ACViewer
A note on
Pathvs ID: as everywhere in AnvilToolkit, thePathtext next to a reference is a human-readable label; the engine (and other files, like AnimSets) find an animation purely by its numeric ID.
Game support: animation export/import is available for AC2, Brotherhood, Revelations, AC3, AC3 Remastered, Black Flag, Rogue, Unity and Syndicate. Examples here use AC4: Black Flag.
- Core Concept: What an .Animation Is
- The Golden Rule: Load Every Skeleton First
- Step 1: Open the Animation in the Mesh Viewer
- Step 2: Load All the Skeletons It Uses
- Step 3: Export to GLB
- Step 4: Edit in Blender
- Step 5: Reimport the GLB
- Step 6: Save It as a Game .Animation
- Using Your Custom Animation In-Game
- Gotchas & Notes
- Quick Reference Summary
An .Animation file is a per-bone keyframe container. For each bone it animates, it stores a track of keyframes — rotation and translation over time. A few important properties:
- It is skeleton-agnostic. An animation stores no skeleton reference. Its tracks are keyed to bones by the bone's name hash, not by any particular skeleton. That's why the same animation can be pointed at different characters, and why the animation swaps in Lesson 5 work — the game matches tracks to bones by name.
- It runs at 60 fps. Keyframe times are stored as ticks at 60 frames per second. This matters when you get to Blender.
- It is referenced by ID. Nothing inside the animation says who uses it; other files (AnimSets and the like — see Lesson 5) point at it by its ID.
Because tracks are keyed by bone name, the animation only "knows" about bones by name — it has no idea which skeleton(s) those bones live on. You have to supply that context by loading the right skeletons, which is what the next section is about.
Animations for a character live alongside its other data (in AC4, in the character/gameplay data files). You open them straight from the Game Explorer.
When the Mesh Viewer exports an animation to GLB, it does not walk the animation's tracks and write them out. It walks the bones of the skeletons you have loaded, and for each bone asks "does the animation have a track for this bone?" If yes, it writes a glTF channel for it. If a bone isn't loaded, the question is never asked.
The consequence is critical:
Any track whose bone is not present in the loaded skeletons has nowhere to bind, so it is silently left out of the GLB — with no error and no warning.
A character's bones are usually spread across several skeletons:
- a base/main skeleton (the body rig), plus
- one or more addon skeletons (weapons, hair, hood, physics bones, etc. — see the Skeleton deep-dive).
If your animation moves, say, a sword bone or a hair bone, and you only loaded the body skeleton, those tracks vanish from your export and you'll never see them in Blender. So:
Load the base skeleton and every addon skeleton the animation touches before exporting. Loading extra skeletons is harmless (bones with no track are simply skipped); loading too few loses data.
In the Game Explorer, find the .Animation you want to edit and double-click it. It opens in the Mesh Viewer as an animation frame in the scene tree.
At this point the viewer has the animation data but nothing to play it on.
Now bring in the skeletons (see the Golden Rule for why all of them).
- Load the character's main body skeleton first — the first skeleton you load becomes the main skeleton.
- Load every addon skeleton the animation uses (weapons, hair, hood, etc.).
With the skeletons loaded, the animation now has bones to drive. Loading a mesh too (the character's body) is optional but makes it much easier to tell the animation is correct.
How do I know which skeletons an animation uses? Load the character's main skeleton plus all of its addon skeletons (the same set the character loads in-game). If in doubt, load them all — extras are ignored during export. The Skeleton deep-dive explains how a character's skeletons fit together.
With the animation and all its skeletons loaded, export the scene:
- Use the viewer's Save / Export and pick "Scene - glTF 2.0 (*.glb)".
- Do not pick "Separate Meshes - glTF 2.0" — that option exports meshes only and does not include the animation.
The resulting .glb contains:
- the armature — all the bones from every skeleton you loaded, and
- the animation — one glTF channel per bone that had a track, holding its rotation and translation over time.
Open the .glb in Blender.
- Set the scene frame rate to 60 fps. Game animations are stored at 60 fps; matching Blender's frame rate keeps every keyframe's timing exact through the round-trip. (Output Properties → Frame Rate → 60.)
- Use the AnvilToolkit Blender import/export presets so orientation and scale stay consistent with the mesh workflow.
- Do not rename the bones. On reimport, tracks are matched back to game bones by node name — rename a bone and its track will no longer map to the right game bone (or will be lost). Edit the animation, not the rig's names.
- Edit the existing animation, or key a brand-new one on the same armature.
- Export back out of Blender to a
.glb(again using the preset).
Back in the Mesh Viewer, import your edited .glb:
- Drag and drop the
.glbonto the Mesh Viewer window. - In the Mesh Import Options dialog, make sure "Animations" is checked. (Leave the mesh options as you like — for a pure animation edit you only need the animation.)
The imported animation is added to the scene as a new animation frame (or it replaces an existing one with the same ID). Behind the scenes the importer maps each glTF node back to a bone by its name hash and rebuilds the game tracks — which is exactly why keeping the bone names unchanged in Blender matters.
With your animation frame in the scene, save it back to the game's format:
- Use the viewer's Save dialog and choose the
.Animationfilter for the active game. - Give the file a name. The animation's ID is generated from the animation name you set in Blender. The ID can be edited in the Mesh Viewer or by exporting the animation to XML.
Same game only. You can't save an animation into a different game than the one it was loaded from. To move an animation between games, export it to XML and reimport it on the other game instead.
Saving the .Animation is only half the job — something has to reference it. The game plays animations by ID, so you make a character use yours by pointing a reference at your animation's ID. Two approaches:
- Replace: save your animation with an existing animation's ID (Step 6). Everything that already points at that ID — including AnimSets — now plays your animation, no other edits needed.
-
Add and repoint: save your animation with a new ID, then edit the AnimSet that drives the character so its
TargetAnimationpoints at your new ID. This is exactly the AnimSet editing covered in Lesson 5 – Animations.
Then repack (Data → Forge) as usual and test.
- Load every skeleton before exporting. (Yes, again — it's the number-one cause of "half my animation is missing.") Missing skeleton → missing tracks, silently.
- 60 fps. Keep Blender's scene at 60 fps or your keyframe timing will drift.
- Don't rename bones in Blender. Tracks re-map by node name on import; renamed bones lose their tracks.
- Rotation + translation only. Those are what export and reimport; that's all animation editing needs.
- Keyframes come back linear. Imported curves are resampled as linear keyframes, so very sparse, heavily-interpolated curves may look slightly different — add keyframes if you need finer control.
- Skeletons must match the animation. Load the skeletons whose bones the animation actually uses (the character it was built for). Wrong skeleton = its bones don't match the tracks and those tracks drop on export.
-
Porting between games: use XML export/import, not the
.Animationsave (which is locked to the active game).
| Thing | Detail |
|---|---|
| What an .Animation is | Per-bone rotation/translation keyframes, keyed to bones by name hash, at 60 fps, skeleton-agnostic. |
| How it's used | Referenced by ID from AnimSets/other data (see Lesson 5). |
| Before export | Load the animation and every skeleton it uses (base + all addons). |
| Export | Viewer → Scene - glTF 2.0 (*.glb) (NOT "Separate Meshes"). |
| In Blender | Scene at 60 fps, use the AnvilToolkit presets, don't rename bones, edit the animation. |
| Reimport | Viewer import → .glb → Mesh Import Options with Animations checked. |
| Save | Viewer Save → .Animation for the active game; ID comes from the filename. Same game only. |
| Use in-game | Replace an existing animation's ID, or point an AnimSet's TargetAnimation at your new ID (Lesson 5). |
| Supported games | AC2, Brotherhood, Revelations, AC3, AC3 Remastered, Black Flag, Rogue, Unity, Syndicate. |