Blender in, game out: the machine that builds D-0066
D-0066 is rebuilt from source by script, the same way every time. Change anything (a vertex on his knuckle, the grip on a rifle, the width of a stitch) and one command rebuilds the body, and one command rebuilds every animation.
I build the tooling with a coding AI. The AI writes the code. I decide what it does, and I check it line by line.
Three chains, one skeleton
| Chain | Goes in | Comes out |
|---|---|---|
| Mesh | The generated body, swapped-in hands, eyes, mouth, cigar, every hand edit | One rigged body on the frozen skeleton |
| Texture | The generated texture | A cleaned coverall, skin and face, with the wear written in |
| Animation | Raw animation downloads | Over 130 clips, baked and checked for the game |
The skeleton never changes. Both of his bodies, the earlier MakeHuman one and the current one, sit on the same skeleton, so the animation chain does not care which body it is feeding. When the new body arrived, it was fitted to the rig, not the other way round: a copy of the skeleton is fitted inside the new mesh, the old body's skin weights are handed over to it, and the mesh is posed back onto the rig. The joints end up where they were, to a thousandth of a millimetre.
The mesh chain
Around forty steps. Each one fixes one thing, and each one has a name, so a fix is never a mystery later.
- Hands. The generated fingers were flat slats. They are cut off at the cuff and replaced with MakeHuman hands, taken from 6 cm inside the sleeve so the join stays hidden.
- Eyes. Real eyeballs set into opened lids, replacing eyes that were painted onto the face. True spheres, after a first version that wasn't.
- Face. The generated mesh's face was too coarse, so it was swapped for a reduced cut of the original high-detail model. The head gets the triangles, and the body gets fewer.
- Mouth and cigar. The lips are split and modelled open. The cigar is built by script, down to the ragged ash ring and the glowing tip, and the lips wrap around it.
- Weights (how the skin follows the bones). A run of named fixes. Wrists that twisted like a candy wrapper got twist bones. Skin hidden under the collar, hair and boots copies the movement of whatever covers it, so it can never poke through.
Hand edits are data. When I fix something by hand in Blender, the fix is read back out of the file (moved vertices, added faces, UVs, painted pixels) and stored. Every rebuild replays it. A rebuild never undoes a hand fix, and a hand fix never has to be done twice.
The texture chain
The generated texture comes with lighting baked into it, so the first step strips that out. Then the coverall gets a second set of UVs for a tiling twill weave, its painted-on folds are calmed down, and a detail step writes in the wear: dirt in the creases, worn knees, elbows, seat and cuffs, stains, stitching. Every detail is a named entry in code, so it comes out the same on every rebuild.
The number on his back goes on last, because every earlier step drew seams through it.
The animation chain
raw download never edited
→ in place the game moves him, not the clip
→ shaped hips, pelvis, swims upright
→ grounded against the soles of HIS boots
→ torso set one per thing he can hold
→ grips, poses hand-made, replayed as data
→ twist bones
→ baked for the game
→ verified every joint, every frame
- Legs and torso are separate. The legs play on one layer, the torso on another. A crouch-walk with a rifle is the crouch-walk legs plus the rifle torso. So a new weapon needs one new torso set, not a new copy of every leg move.
- Made in place. A walk downloaded from Mixamo travels well over a metre per loop. The chain takes the travel out and keeps a few centimetres of sway, because the game moves him itself.
- Heavily edited. The unarmed idle started as a boxing idle with the torso motion cut down to almost nothing. The heavy-weapon idle is a pose I built by hand, turned into an idle with two uneven breaths. The ladder climb was moved, turned round and measured, so the game knows the rung spacing.
- Where it comes from. Most of the raw material is Mixamo. The throwing and two-handed melee sets come from two other animation packs. None of it is used as it came.
Why the bake exists. Blender and Unity read the same animation file differently: Blender plays each bone relative to its rest pose, Unity plays the raw values. Unbaked, every clip would have played 3 to 13 cm off its preview. The bake rewrites each clip against the rig, puts a key on every frame, and the last step proves the game file matches the preview. Unity's own animation compression moved joints by up to 17 mm, so it is switched off.
The cache
Rebuilding everything from scratch takes a while. Mostly, nothing has to be.
| What changed | Rebuild time |
|---|---|
| Nothing | 8.5 s |
| One clip | about 20 s |
| Everything, forced | 8 min 47 s |
A step is skipped only when everything it touches is byte-identical to last time: its input files, the command itself, the script it runs, and every module that script imports. Contents, never dates. If a later step overwrote a skipped step's output, the old output is restored from storage instead of re-running the step. Every file is hashed once per run, in one go, because on Windows starting thousands of small processes is the slow part.
The chains also know what drags what along with it:
| Change | What gets rebuilt |
|---|---|
| His body shape | The whole body |
| Anything that moves his soles (boots, height) | Every clip gets re-grounded |
| His hand width | The two-handed melee set re-spaces his grip |
| A clip approved or dropped | Only that clip gets baked |
The cache also caught a bug. One step edited a clip in place, so each rebuild processed its own output again. The pistol run clip was processed three times, and his spine sway nearly doubled until he looked like he was dancing. Now every rebuild starts from an untouched copy of the raw downloads. About half the clips changed when that went in.
The previewer
Every animation clip on the D-0066 page came out of the previewer. It renders him the way the game assembles him (body, clothes, eyes, teeth, hair, cigar) in Blender's real-time renderer, from up to nine standard views: front, side, back, flat orthographic views for checking angles, and the slow three-quarter orbit you see on the site. Each clip is rendered once and played three times, so a bad loop seam shows.
It queues one Blender per clip per view, in a rolling pool: the next render starts the moment there is room, not in batches. "Room" means memory. A new Blender only starts if 10 GB of RAM stays free with it counted as 2 GB, and every Blender on the machine counts, whichever previewer started it. Several previewers can run at once and share one view of the machine. Every render runs at below-normal priority.
Then it melted the PC. The memory gate limits memory, not load. With plenty of RAM it let eight previewers start 21 renders at once: CPU at 100%, graphics card at 100%, desktop unusable. Lower CPU priority did nothing, because the renders were on the GPU. So now a throttle watches the whole machine every five seconds:
| State | For | Then |
|---|---|---|
| CPU over 80% or GPU over 90% | 15 s | Pause the newest render (suspend it, never kill it) |
| CPU under 60%, GPU under 70% and video memory under 90% | 15 s | Resume the oldest paused render |
After each change it waits another 15 seconds, so it doesn't flip back and forth. At least one render always keeps going, and my own programs count toward the load. A long render also gets a budget: if a clip is estimated at over five minutes, it drops to 30 fps, and then to a smaller frame.
Why bother
Because he is going to change again. When he does, every fix already made stays made and the whole set rebuilds in minutes. The previewer shows exactly what moved.
There is no gameplay yet. That is next.