Second Chance GazetteDevlogToken Use

Shuffle Turns

unreal-enginesnookeranimationmetahumanroot-motionfoot-skatesound-cuecrashblueprintplaytest

A Wednesday with the allowance back

The weekly allowance came back on Wednesday, and by evening there were five sessions of the agent - Claude Code Opus 5.5, a day old in James's hands - sharing one copy of the editor. One was on the new fox. One was writing the dialogue for a woman in the nightclub. One was fitting out the club's toilets. One was on number plates. The one this entry is mostly about spent the evening making two men walk round a snooker table and turn to face it.

Only one session at a time is allowed to press Play, so they took turns and messaged each other, which is roughly what a studio corridor sounds like with fewer people in it.

The snooker hall is where the week had got to. On Tuesday the two players, Barry and Mervyn, had played a whole frame on their own and James had played one against Barry, and the video of both is up. The frame was the good news. The walking was not. James had written it down in one breath: when he turns he slides and at first seems to move the other way, and then he wanted the whole sequence - stand up from the shot, relaxed, one step back, turn on the next step, then a normal upright walk, not slouching, not walking like an ogre.

That is four animation problems in a sentence. Rockstar have a motion-capture stage for this. He had a list and a Wednesday evening.

The handshake at the corner

The first job was left over from the frame: at the end of it the two men had walked together to shake hands and then, in James's words, come together and gone apart again. They shook at 188.7 cm apart. The plan said 130.8.

The agent built a sampler that recorded both men every tick - where they stood, where their hands were, which clip was playing - and the numbers told it plainly. Barry stood exactly on his mark. Mervyn stood 87 cm off his.

The men walk on a rectangle drawn round the table, and positions on it are stored as a distance along the edge plus an offset out from it. The meeting point had landed 9 cm from a corner, so Mervyn's mark sat diagonally out past the corner - somewhere the rectangle's maths cannot describe. It rounded him onto the corner, then put him back out along one side only. The two conversions are exact inverses on a straight side and not at all on a corner.

The same sample turned up something worse. Every man walking off the ring jumped round each corner in a single tick - 100.5 cm for one, 123.4 cm for the other - and his facing snapped 90 degrees on the same frame. Each straight side's offset line simply ended in a different place from where the next began. It had been there since the ring was built. Most of James's came together and went apart was this.

The corners now blend across the last 40 cm, and the meeting point is kept far enough from a corner that it never lands inside the blend. The next run shook at 130.9 cm. The blend left a cost of its own: the men now take a corner at more than twice walking speed for about seven tenths of a second. That one is still on the list.

A bearded man in a dark waistcoat, white shirt with rolled sleeves and dark tie stands beside a snooker table holding a cue upright with its butt on the floor, looking down the table at a rack of reds. Brass sconces and a shaded table light hang on the papered wall behind him, with the club counter and a doorway onto a sunlit street at the left.
Mervyn with his cue upright in his right hand - the standing hold the left-handed grip was mirrored from.

James added a small thing. They should really swap the cue into their left hand as well so they can both shake with their right hands. The agent mirrored each man's standing hold across his own body and slid the grip down the shaft until the butt sat a centimetre off the floor. The left arm hangs lower than the right, so the left-hand grip came out about 20 cm further down the cue. In play the butt wandered between 3 cm under the floor and 14 cm above it with the sway of the clip, and both cues went back into the right hand after the shake.

Ninety minutes in, after two runs in play, the editor ran out of memory mid-build - 107 GB of virtual memory, a paging file too small. Three of the four rewritten graphs had saved. The fourth had not. The script was made resumable before it was run again.

The ogre walk

The walk looked wrong because the men sank when they set off. A measurement the previous week had put the head 20.6 cm lower walking than standing, and the note that stood in the handover said the crouch was in the clip and that the clip's bone translations did not reach the render.

The agent measured the posture before touching anything. The trunk was 2.4 degrees off vertical walking and 2.7 standing. Nobody was leaning. What differed was length: the walk had been made on a different body, and it carried that body's bones. Pelvis to head, 56 cm walking against 72 standing. Worked out offline, the difference came to 20.7 cm, which is the 20.6 measured in play to a millimetre. So the translations did reach the render, and last week's note was wrong about that.

The fix was to give five clips - the walk, its start and stop, and both turns - the standing idle's bone lengths, keeping every rotation, and to lower the pelvis until the lowest foot landed where the idle's does. The head came up from 139 cm to 155.6, a normal walking bob below the idle's 159.7. Longer legs meant a longer stride, so the walking speed went from 118 to 124 cm a second to keep the feet honest.

James watched it. I didn't notice any unusual walking. That was the whole review.

A shuffle, not a step

The turn took the rest of the night. It would end with the feet lifting properly and the planted foot still sliding 20 cm, which is a better place than it started and not the place it was meant to reach.

The agent measured it first: every turn in place skated the planted foot 23-46 cm while the man himself stood still. It blamed an earlier fix. To stop the turn clips spinning the men twice, somebody had stripped the rotation out of the clip's root and left the actor to turn itself, and that strip had also removed 22-25 cm of sideways drift - the clip pivots round one foot, and without the drift the body pivoted on its own middle. So the agent built what that implied. The man now rotated about whichever foot was lower. It also replaced the old 90-degree snap at the end of every walk with a proper turn into the shot.

James watched that too. The snap was gone - that looks a lot better - and the slide was not. Barry turns round, his head lowers and he does seem to slide rather than step. The numbers agreed with him: 24-72 cm for the turn before a walk, 27-58 for the turn into the shot.

The agent measured the clip again, properly this time. The strip had not removed the turn from the animation; it had moved it into the feet, so pivoting the actor round a foot counted the turn twice. Driving the actor with the exact curve that had been stripped out still left the planted foot sliding 18-22 cm. The reason was in the clip itself. These turns lift the feet between 1.8 and 4.7 cm. They are shuffles. A shuffle does not become a step whatever is done to the body carrying it.

James went looking for a replacement and found one in the project's own Mixamo pile: a man turning round with a box. This one is most similar - the difference is the hand position. The MetaHuman copy of it is a real step-turn: 91 degrees to the left, the right foot then the left, lifted 10-11 cm. There was no right-handed version anywhere in the project, so the agent mirrored it, then forced both arms onto the cue hold so nobody would be carrying an invisible box.

It had written itself a gate: the planted foot must travel no more than 6 cm. The new clip failed it. So did the original, played with its own root motion - 10.5 cm, because a real foot rolls from heel to toe. The gate was set at the source's own score plus 3 cm, and the new clips came in at the source's score.

Wired in, the men now lift their feet through the turn. The first run in play then showed turns that hung for 7-9 seconds. The clip loops, and the check for its last frame asked for a value the looping clock never quite reached before wrapping back to zero. That was fixed just before midnight. Measuring it again in play is the first job.

The planted foot still slid 20-26 cm on normal-length turns. The agent listed three suspects, in order, and left them for the next session.

The Scalability dialog that would not listen

A side story, and a trap other people will hit. The editor was on Epic and running at one to three frames a second in play, which is useless for judging a walk, because 2.5 GB of video memory was over budget. The agent turned everything down with console commands. James then tried to change it back in the Scalability dialog and reported that something was immediately turning it back to Epic.

It was the agent. Settings written from the console outrank the dialog until the editor restarts. The second attempt used the game's own settings object, which leaves the dialog working.

British snooker, and where the stance comes from

The last of James's notes was about the address. Both men bent at the hip with both legs straight, which nobody does. Make their stances conform with British snooker rules if it specifies how to do various poses.

The agent looked, and reported that the rules do not specify it. The WPBSA rules only require one foot on the floor at the moment of the strike. The stance - right foot on the line of the shot and braced, left foot forward with the knee soft and carrying the weight, chin over the cue - comes from the WPBSA's coaching material. That is what the men are being rebuilt to.

It is a small thing and it is the point. GTA 6 is set in a version of Florida. This is a British snooker hall with a full-size table, the proper stance and two men who shake hands with the correct hand at the end.

The fox that crashed the editor

The fox thread had bought a new fox from Fab and given it a new brain. The editor crashed as a test put the player five metres from one.

A red fox standing side-on against a plain black background, head turned slightly towards the viewer. Russet coat, white throat and chin, black ears, black lower legs and a white-tipped bushy tail.
The new fox, rendered on black to check the mesh. The crash that came with it had nothing to do with the fox.

There were no debug symbols installed, so the agent wrote a forty-line reader for the engine's export table and matched the crash addresses to their nearest names. The call stack did not go anywhere near the fox. It went through the audio device, into the playback of a sound cue, into a Random node, and out through an array read past its end.

The player standing close had frightened the fox, the fox had run, and running plays a bark. It was the first bark of the project's life. That cue had been built from Python three and a half hours earlier in the same editor session, and a Random node set up that way keeps a hidden list of which sounds it has used that nothing had sized. A cue loaded from disk sizes the list on load. A restart fixed it, and the import script now says so at the top.

The same session found the fox's bin-tipping jump had never been reachable: two transitions were checked in the wrong order and the first one reset the timer the second one needed.

Christie

The nightclub session spent the evening on a woman called Christie, who is on the dance floor at the club and whom the player can talk to or ignore. James had asked for research into what people want from the nightclubs in GTA 6 first. Her lines are text, on three number keys, and they do not stop the game. The first stage - meeting a stranger - is built and logic-checked, and playing it through is next.

A dialogue box on a plain white background. A mauve panel headed 'Christie' reads: 'You've been holding that pillar up for twenty minutes. It's not going anywhere, love.' Below it three numbered choices read Option one, Option two and Option three, above a thin pink timer bar.
The dialogue panel as it renders. The choices are layout placeholders; the written lines go in through the dialogue data.

The snooker session released the editor at two minutes to midnight and left it on Low.

The fault

MetaHuman NPC walks crouched with the head 20 cm low - retargeted walk clip in Unreal Engine 5.8

Walk head height 139 cm against 159.7 standing. Read as a lean or crouch for a week. The trunk angle was 2.4 degrees walking against 2.7 standing, so it was not.

The walk clips carried a different base body's bone translations: pelvis to head 56 cm against the idle's 72. The offline difference, 20.7 cm, matched the in-game drop of 20.6. Bone translations in the clip do reach the render.

The fix

Give the walk clips the idle's bone lengths, keep their rotations

On each clip, every bone except root and pelvis takes the standing idle's frame 0 translation (52 tracks). Rotations and scales are untouched. Pelvis keeps its keys plus one height offset so the lowest foot lands on the idle's foot height. Rebuilt from a backup every run.

Then re-measure the clip speed - longer legs make a longer stride (164 to 172.4 cm/s here) - or the feet skate.

Guard: measure trunk angle and bone lengths separately before calling it a posture problem.

The fault

Turn-in-place animation slides - planted foot skates 20-70 cm in Unreal Engine 5.8

The actor rotates; the foot that should be planted travels 23-46 cm per turn. Pivoting the actor round the lower foot made it no better (24-72 cm), and driving the actor with the clip's own stripped root curve still left 18-22 cm.

The clips lifted the feet 1.8-4.7 cm. They were shuffle turns. With the root yaw stripped, the turn had moved into the feet, so pivoting the actor counted it twice.

The fix

Use a real step-turn clip and drive the actor from its root curve

Found a clip that steps (foot lift 10-11 cm, 91 degrees), mirrored it for the right turn, forced the arms to the cue hold, stripped its root yaw and drift to a curve, and moved the actor along that curve each tick on the clip's own clock.

Guard: gate foot travel against the SOURCE clip's own score, not a fixed number - a real foot rolls heel to toe, and the source scored 10.5 cm against a 6 cm gate. Second guard: a looping clip never reports its last frame; test for "last minus a frame and a half".

The fault

NPC teleports about 1 metre at the corner of an offset path, and a meeting point misses by 87 cm

Positions on a rectangular ring stored as distance-along-edge plus offset out. Crossing a corner with an offset moved the man by root 2 times the offset in one tick (100.5 and 123.4 cm) and snapped his facing 90 degrees. A point placed diagonally off a corner converts to the corner, then back out along one side only.

The fix

Blend the corners and keep marks out of the blend

Within 40 cm of a corner, interpolate between the two sides' offset lines, extended, and between their headings. Clamp any mark at least blend width plus 5 cm from a corner. The handshake then measured 130.9 cm against a planned 130.8.

The fault

Unreal Engine 5.8 editor crashes in USoundCue::Parse - SoundNodeRandom array index out of bounds after building the cue in Python

Call stack: audio device update, active sound wave instances, USoundCue::Parse, the Random node's ParseNodes, then an array range check. The Random node with randomize-without-replacement reads a transient HasBeenUsed array that is sized on load or by the editor's own child-node calls. Setting child_nodes from Python sizes nothing, so the first play of the cue in that editor session reads past the end.

The fix

Restart the editor after building a Random-node cue from Python

A cue loaded from disk sizes the array on load, so a restart clears it. Re-running the import re-arms the crash until the next restart, and the importer's header now says so.

Also: console sg.* writes outrank the Scalability dialog until restart and make it look broken. Set scalability through the game user settings object instead.

The kit

ToolWhy this one
A per-tick sampler in editor Pythonrecorded both men's positions, hands and clips every tick; every number above came from it
Offline clip measurementsettled "crouch" against "bone length", and "bad driving" against "shuffle clip", without guessing
A Mixamo carrying-turn clipJames's pick; the only real step-turn in the project
A 40-line export-table readerturned raw crash addresses into function names with no symbols installed

Plain English

TermWhat it means
root motionThe movement baked into an animation clip itself, stored on the skeleton's top bone. A walk clip can carry the forward travel, a turn clip the rotation. The game either lets the clip move the character, or strips it out and moves the character some other way - and if the two disagree, the feet slide.
foot skateA foot that should be planted on the floor sliding across it instead, because the character is moving at a different speed or angle from the one the animation was made for. Measured as how far a foot travels while it is meant to be still.
MetaHumanEpic's system for realistic human characters - face, body, hair and clothing, ready to animate. Every named person in the game is one.
MixamoA free online library of motion-capture animations, made to be dropped onto your own characters. Cheap performances, at the cost of a conversion step that can quietly go wrong.
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.
sound cueA small wrapper around one or more sound files that the game plays instead of the file itself, so the same recording can be reused under several names or mixed with others.
call stackThe list of functions that were running, each inside the last, at the moment a program crashed. Read from the top it says what the engine was doing; read from the bottom it says why.
scalability settingsThe engine's quality dials - shadows, textures, effects, anti-aliasing - each of which can be set independently. Turning one up can cost far more than turning the rest up together.
tickCode that runs every single frame. Cheap once, ruinous sixty times a second across a thousand actors.
OOMRunning out of memory, at which point the program stops.

Things we still need to fix tomorrow:

  • Re-measure the step-turn in play with the loop fix in; the planted foot still slides 20-26 cm, suspects in order are frame lag, turn angles other than 90 degrees, and the walk start.
  • Men take the ring's corners at twice walking speed for about 0.7 s.
  • The two men walked through each other once; find out why the detour did not fire.
  • The step back becomes two small steps with the knee lifting, and the right leg's knee direction gets fixed.
  • The address stance rebuilt to the WPBSA coaching position.
  • Heads follow the moving ball, then settle.
  • The fox's bin jump and flee get a run in play.
  • Christie's first conversation gets played through.

← 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