Second Chance GazetteDevlogToken Use

Follow-Through

unreal-enginemetahumananimationretargetingnvidia-kimodotext-to-motionblenderdartsnpc-routinescollisionstep-heightclaude-codegta-vi

Pointing

Edward drinks in the Slag & Slurry, and if you ask him he will play you at darts. It is 501, on a board in a wooden cabinet at the back of the pub, with a chalk panel either side. After every visit he walks up to the board, pulls the darts, and chalks what you have left. GTA VI is set in a version of Miami. This is a Midlands pub where the regular keeps the score.

Until just after midnight on Thursday, Edward threw his darts with a clip borrowed from a gardener. It was a pointing animation, the closest thing the project had, and from across the pub it more or less passed. The dart came out of a hand that was not moving.

It was a Wednesday, so James was at work, and most of the day ran without him. The agent, Claude Code Opus 5.5, worked in several sessions under a planner, each taking its turn on the one copy of the editor, and he answered their questions in the gaps. The darts were the last job of the evening. The new throw from the night before had been saved and never seen running, because the editor had fallen over six minutes after the save.

It ran at about ten past ten. The dart followed his finger properly and flew on an arc and stuck in the 20. The first thing the stills showed was that you could not see any of it. The camera for his turn sat behind his left shoulder, and he throws with his right, so for the whole throw his own back was in the way.

From behind and to the side, a bald man in glasses and a check shirt holds a dart up at shoulder height towards a dartboard in a wooden cabinet, the chalk panels either side headed EDWARD 501 and YOU 501, on navy and gold crested wallpaper.
Edward aiming, from the new camera behind his right side. The dart is in his hand, which was the point of the night before.

The agent moved the camera behind his right shoulder, widened it, and had it drift across to the board as the dart flew. Then it changed the timing, because the borrowed clip held the arm up and still for most of a second. Edward now aims for 0.8 seconds with the dart raised and lets go at 1.2. The dart left nose-up at about 20 degrees, landed nose-down, wobbled, and stopped.

The same man seen from behind his right shoulder with his arm extended towards the board, a green-flighted dart in the air between his hand and the cabinet.
The release. The dart is in the air and his arm has already finished moving, because it never really started.

It looked like a man pointing at a dartboard, and then a dart arriving in it.

Describe it in words

James had already decided what to do about that, earlier in the day, for a bigger reason than darts.

NVIDIA have released a model called Kimodo. You describe a movement in a sentence, and it generates the animation: a skeleton moving the way the sentence says. The code is open, and the models it uses are licensed for commercial work, with NVIDIA claiming nothing over what comes out. For a game with a hundred residents to animate, that is the difference between waiting for somebody else's motion-capture pack to have the right move in it and writing one down. James asked the agent to install it and prove it on one clip, end to end, onto one of the game's characters.

The install took most of the day and was not elegant. The C drive was 97 per cent full, so everything went on D. The first install failed because the package builds a small piece of C++ for cleaning up foot contact, and that needs CMake. The agent installed CMake. The second failed in exactly the same way, because pip builds packages in a sealed-off copy of the environment, and the CMake it had just installed could not see itself from in there. The third told pip not to seal it off, and found the Visual Studio compiler on its own. Skipping the foot clean-up is a supported option. The agent's notes ruled it out in one line: without it, every clip would skate.

The model reads the sentence with Meta's Llama 3, eight billion parameters of it, and Meta's copy sits behind a manual approval. James chose an ungated mirror instead. The agent checked it against Meta's own before trusting it: every one of the four weight files, the tokenizer and the config had the same checksum. Then it hid the graphics card.

Running Kimodo on the card wants about 17 GB of video memory. The card has 8, and the editor wants all of them. So it runs on the processor, which is slow and needs no card at all, provided the program cannot find one. The usual way to hide the card is to set one setting to nothing. On Windows, nothing does not survive the trip: the empty setting is dropped before the program starts, so the program saw the card anyway. The agent caught it with a one-line check that printed True where it should have said False. Setting it to minus one works.

The first generation went in at the end of the evening: a man throwing a dart overarm with his right hand, described in plain words. One run of it took about 19 GB of the machine's memory and nothing from the graphics card, and four takes took around five minutes. One of the four walked 51 centimetres across the floor. One threw too early, with no wind-up. One was late. The second take was the one: a rise, a cock by the ear, a flick, and a follow-through.

Six grey block figures on black, three seen from the side and three from the front, showing a standing pose, the throwing arm raised and cocked by the head, the arm thrown out straight forward, and the arm coming back down.
The chosen take on a block-figure stand-in, side and front: standing, the arm cocked behind the head, the flick out straight, and the arm coming down.

On the way, the agent found that a full stop in the prompt splits it in two. Each sentence becomes its own segment, at the full requested length, so a three-second throw with a second sentence about planted feet came back as six seconds: the throw, then three seconds of a man standing still.

Quarter past twelve

Getting the clip into Unreal turned up two more. The script that turns Kimodo's animation file into something Unreal imports exported 250 frames for a 90-frame clip, because the Blender call it used to fit the scene only ever makes the range longer. And the first import came in with every bone laid flat along one axis at hip height, which is how Kimodo's default rest pose looks. The motion was identical either way, but the retargeter lines two skeletons up by their rest poses, and a man lying flat in mid-air lines up with nothing. Kimodo will re-export a take with a standing T-pose rest without running the model again, which took seconds.

The bone names turned out to be the same as a motion pack already in the project, so the retargeting setup that existed for that pack took the new clip onto Edward unchanged, fingers included. The agent measured it before calling it done. In the source take his feet drift less than 2 centimetres. On Edward, his hand is cocked at 175 centimetres by frame 44 and flicks forward 51 centimetres in the next four frames. It moved the release in the darts game from 1.2 seconds to 1.5 to match.

At about a quarter past twelve Edward threw his first one.

Looking over the top of the bald man's head at the dartboard, with a dart in the air just short of the board near the 20 and both chalk panels still showing 501.
The new throw in play. The dart is in the air just short of the board, both panels still on 501.
The bald man's head and his right hand open beside it after the throw, the dart stuck in the top of the board near the 20.
The follow-through, his hand open by his head, the dart in the top of the board.

The frame where his arm is cocked behind his head was not caught. The editor was in the background, and in the background the screenshots lag half a game-second behind what they claim to show. The held dart sits behind him during the wind-up, which may or may not read right. That is tomorrow's.

The darts were the test. The reason is walking. Every resident in the town walks with a clip recorded at one speed and is moved along at another, so most of them march, legs going three times faster than they travel. Kimodo can be told where the body goes as well as what it does, so it should be possible to make each walk at the speed that resident actually moves. The first clip on James's list is still the one he started with: somebody putting an umbrella up.

The same evening, an audit of the residents' routines found the other half of that job. Every action a resident takes asks for an animation by name, and every name pointed at an empty list. The code that plays them also only knows one kind of animation asset, and the residents are driven in a way that ignores that kind entirely. So there were two separate reasons nothing played, and one small change to the town code would answer both. That goes to the town thread as a proposed change.

NVIDIA have a research lab for this. He had a Wednesday and the D drive.

On the wall

Earlier, in the afternoon, a resident called Ellie had taken a photograph from the top of a garden wall.

The residents report things. A pothole, a fly-tipped mattress, graffiti, a bin knocked over: one of them spots it, walks up, gets their phone out and photographs it for the council. Ellie had done it properly in every way but one. She was standing on the corner pier of an end-of-terrace garden wall, about 60 centimetres above the pavement, photographing a mattress in the road.

A woman in a red dress stands on top of the corner pier of a low brick garden wall in front of a terraced house, holding a phone up towards a white mattress lying in the road, with a large stone building beyond.
Ellie reporting a fly-tip from the top of a garden wall, phone up, as if it were the most natural place to stand.

A rule had already gone in that day: no photograph if the reporter's feet are more than 30 centimetres above the thing being reported. That stopped the picture. It did not stop anybody standing on walls.

The agent went looking for a hole in the navmesh and did not find one. The walls are part of the house model, the walking map does not route anybody over them, and a search for a way up found none. The cause was the capsule, the invisible shape a character actually walks as. A character may step straight up anything 60 centimetres high, and the piers are 61. That sounds safe until the pavement is measured. On this terrace the pavement sits up to 27 centimetres higher than the houses' own ground, and 48 of the 64 wall tops were only 34 to 50 centimetres above it. Anybody brushing past a pier could be lifted onto it by their own feet, and the route carried on from up there.

Lowering the residents' step to 50, which had gone in, does not cover it. Getting under the walls would have needed about 30, and the town has kerbs between 30 and 55 centimetres that people need to climb. So the agent proposed boxes: invisible, sitting on top of every pier and side wall, blocking walkers and nothing else. They would mean the player could not hop up on those walls either. James sent two words back. Block everyone.

Sixty-four boxes went onto 16 houses, the gateways left exactly clear. In the editor, every one of them read back as blocking walkers only. In play they blocked everything: the camera, line-of-sight checks, the very trace the photograph code uses. Invisible boxes two metres high over every front wall in the street.

A terraced street in the editor with flat white boxes sitting on top of every front garden wall and gate pier, chest high, leaving the gateways to the front doors open, and green wheelie bins on the pavement.
The boxes, shown in the editor, on every pier and side wall of the terrace. In the game they are invisible.

Each box was a plain cube, and each kept a tick in a box that says use the mesh's own default collision. The editor shows the custom settings. The game, at start-up, goes with the cube's, which block everything. Unticking it on all 64 and saving took two minutes. In the re-test, walkers stopped at the wall tops and the camera and every other check passed through. A resident had already walked past the pier Ellie stood on in the first test, 10 metres in eight seconds, without catching on anything.

Elsewhere on the estate

The rest of the day went on houses. On Kelsthorpe, three of eight derelict houses were dressed and saved, 140 pieces each: 6 Ovaltine Crescent, 61 Bisto Road and 13 Brylcreem Close. The estate agent got its name from James, Barestow Leaves, and 21 property cards for its window, which will go in the empty unit beside the Pleasure Palace. Lee, on the door at the Sweatbox on Mondays and Tuesdays, had been standing 0.7 centimetres inside the landing. His boots now sit 0.2 centimetres above it.

The fault

NPC dart throw: dart hidden behind his own body and released from a still arm (Unreal Engine 5.8)

  • The turn camera sat behind the thrower's left shoulder; he throws right-handed, so his torso hid the dart for the whole throw.
  • The throw was a borrowed pointing clip. The arm is up and still from about 0.7 to 1.6 s, so any release time lets go from a stationary hand.
  • The screenshots meant to check it: HighResShot with the editor in the background lags about 0.5 game-seconds behind the moment it is taken.

The fix

A camera on the throwing side, and a generated throw with a real flick

  • New throw camera behind the right shoulder at FOV 60, dollying to the board view as the dart flies. Aim 0.8 s with the dart raised.
  • The clip replaced with a Kimodo-generated throw retargeted onto the thrower. Measured on the output: hand cocked at 175 cm by frame 44, forward 51 cm over frames 44-48. Source take: hand peak 5.4 m/s, feet drift under 2.1 cm. Release moved from 1.2 s to 1.5 s.
  • The guard: measure the hand's travel on the retargeted clip, not on the source, and check the finger bones follow before wiring a held prop to them.

The fault

NVIDIA Kimodo on Windows: "CMake must be installed to build this package", and the GPU not hidden

  • pip install -e "./kimodo[soma]" builds a C++ extension (MotionCorrection) and fails with RuntimeError: CMake must be installed to build this package.
  • After pip install cmake it fails again with ModuleNotFoundError: No module named 'cmake': pip builds in an isolated environment that cannot import the venv's CMake.
  • CUDA_VISIBLE_DEVICES="" does not hide the GPU on Windows. The empty variable is dropped before the child process starts, and torch.cuda.is_available() stays True.
  • Full GPU use needs about 17 GB of VRAM. On an 8 GB card beside the Unreal editor, that is a crash.

The fix

Install without build isolation, hide the GPU with -1

  • pip install cmake "setuptools>=61" wheel into the venv, put the venv's Scripts folder on PATH, then pip install --no-build-isolation -e "./kimodo[soma]". CMake fetches its own dependencies and finds the installed Visual Studio C++ toolchain.
  • Do not dodge it with SKIP_MOTION_CORRECTION_IN_SETUP=1: that drops the foot-contact clean-up and every clip skates.
  • CUDA_VISIBLE_DEVICES=-1. Check with torch.cuda.is_available(), which must print False.
  • CPU-only, one generation held about 19 GB of system commit and no VRAM; four 3-second takes took about five minutes. Start it only with 40 GB of commit free.

The fault

Kimodo clip comes into Unreal Engine 5.8 too long, and retargets badly

  • A full stop in the prompt splits it into segments, each the full --duration: two sentences at 3 s gave a 6 s clip.
  • Blender exported 250 frames for a 90-frame BVH. update_scene_duration only ever extends the scene's frame range.
  • Kimodo's default BVH rest pose lays every bone flat along +X at hip height, which gives the IK Retargeter a nonsense alignment pose.

The fix

One sentence, fit the range, export a T-pose rest

  • Write the prompt as one sentence, or trim the BVH.
  • Set the scene's start and end to the action's frame range before the FBX export.
  • Re-export the chosen take with kimodo_convert take.npz take_tpose.bvh --bvh_standard_tpose. No model run is needed. The motion is identical; the rest pose is usable.
  • Kimodo's 77-joint skeleton uses the same bone names as the Motifect motion pack (Hips, Spine1, LeftForeArm, LeftHandIndex1...), so an existing Motifect retarget chain set bound it, fingers included.

The fault

NPCs climb onto garden walls in Unreal Engine 5.8 with MaxStepHeight 60

Citizens ended up standing on 61 cm terrace garden-wall piers. Not a navmesh fault: the walls are not routed over. MaxStepHeight is 60, and the pavement sits 11-27 cm above the house base, so 48 of 64 wall tops were only 34-50 cm above the pavement. The capsule's own step-up lifted walkers brushing past. A citizen-only step cap of 50 did not stop it; about 30 would, and breaks 30-55 cm kerbs.

The fix

Pawn-only blocker boxes, with Use Default Collision off

64 hidden StaticMeshActors on the pier and side-wall tops (wall top to 200 cm), collision profile Custom: Pawn Block, every other channel Ignore, QueryOnly, CanEverAffectNavigation False, so no navmesh rebuild.

☠ In PIE they were BlockAll: Visibility and Camera traces hit them while the editor world read Ignore. The components still had use_default_collision True, so at runtime the Cube's own collision replaced the saved Custom profile. Set it False, re-apply the profile, save. The guard: the placing script now sets it first and checks it in the readback, and the PIE trace test (Pawn hits, Visibility passes) runs before calling it done.

The kit

ToolWhy this one
NVIDIA Kimodotext-to-motion; code Apache-2.0, the models used are under NVIDIA's Open Model License and commercially usable
Blender 5.1, run headlessBVH to FBX for Unreal
IK Retargeterthe existing Motifect chain set took the Kimodo skeleton without changes
Claude Code Projects (beta)a planner sharing one editor between several Opus 5.5 sessions
Monolith MCPthe PIE tests, the traces and the imports

Plain English

TermWhat it means
text-to-motionA model that makes a character animation from a written description, such as 'a man throws a dart', instead of from motion capture.
BVHA plain-text animation file: a list of bones, then the angle of every bone on every frame.
CUDANVIDIA's way of running calculations on the graphics card; the setting decides which cards a program is allowed to see.
retargetingTaking an animation made for one character and making it work on a differently proportioned one.
rest poseThe neutral pose a character's skeleton was built in, before any animation moves it; the export and the skinning both assume the model is in it.
animation clipOne recorded movement - a step, a sip, a wave - that a character plays back.
MetaHumanEpic's system for realistic human characters - face, body, hair and clothing, ready to animate. Every named person in the game is one.
PIE"Play In Editor" - pressing play inside the editor to test the game without building it first. Fast, and it behaves subtly differently from the real build.
capsuleThe invisible pill shape a character actually walks around as; the body you see is drawn on top of it.
step heightThe tallest ledge a walker is allowed to step straight up; the navmesh and the character each have their own, and when they disagree, people get routed over walls they cannot climb.
navmeshAn invisible map of walkable ground that characters use to work out routes. No navmesh, no walking.
collision profileThe set of rules saying what an object blocks and what passes through it - the player, the camera, a line of sight - one rule per kind of thing.
traceFiring an invisible line into the world to find out what it hits - used for "what is under this object" and "what is the player looking at".
BlueprintUnreal's visual scripting. Logic built by wiring boxes together with lines instead of typing code. This whole game is built in it.

Things we still need to fix tomorrow:

  • See the cocked frame of Edward's throw in play, with the editor in front, and check the held dart behind him during the wind-up.
  • A sound for the dart hitting the board.
  • Edward's 60 lines into the darts game itself.
  • The umbrella clip next, then walks generated at each resident's own walking speed.
  • The town code change so residents' actions can play their clips.
  • The same wall check on the other terraces.
  • Five more derelict houses on Kelsthorpe.
  • The estate agent's window, starting with a survey of the empty unit.

← All devlog entries

Watch it get built. All of this goes up on YouTube as it happens - broken animations, buildings hovering a foot off the ground, the lot.

Subscribe on YouTube