Loyal for Life
A dog that owes you nothing
It was Sunday, so the gym in the morning and his parents later, and the agents carried on in between. By the end of the day there was a stray dog in Second Chance who would eat a ham sandwich out of your hand, five hens that had stopped exploding, four pool tables, a darts match with a scorer, and an estate with zebra crossings in it. The dog was the one that took the longest.
James had given the brief that morning. A stray Staffordshire Bull Terrier roams the streets looking for food. The player can befriend him, take him home and look after him. Feeding him is appreciated. Not feeding him costs nothing at all. Once he is yours he is loyal for life. Halfway through the morning James added the part that made it a design rather than a pet: he should be timid at first, and a bit friendlier each time you meet, especially if you give him something to eat.
That is the whole of the thesis, in one dog. GTA 6 is a story about two other people, and the people and animals in it are there because the story needs you to care about them. This one is a stray. You can walk past him every day for a month and nothing happens. Nobody sends a text. There is no mission. He just carries on going through the bins down the twitchel.
The agent - Claude Code Opus 5.5 - started where it could afford to. There is no free rigged Staffie anywhere on Fab; it searched. James turned down a £27 pit bull with cropped ears, because a stray round here does not have cropped ears. That left a free German Shepherd, and the job of turning one into the other.
It took the rest of the morning. A Shepherd is the wrong dog in every proportion that a British person clocks instantly: the neck is long, the back is long, the tail is long, the head is narrow. James said twice that the head and neck were wrong. The agent tried pushing the skin about over the existing bones and it would not come right, because the bones themselves were the wrong length. In the end it gave him his own skeleton: neck bones cut to two thirds, the back shortened, the tail nearly halved, then a broad skull, a short muzzle, rose ears, a dark brindle coat and a ragged white bib. He stands about 39 centimetres at the shoulder, which is where the breed sits. The collar has a brass tag on it that says TYSON.

The trust ladder
By early afternoon he was in the game, and at twenty past three the agent put him through a test.
He roams at a slow walk and stops to scavenge. Walk towards him while he is timid and he keeps about eight metres off, low, facing you, and backs away if you push it. Hold out a sandwich and he creeps in, belly low, to just over a metre. Give it him and he wolfs it down: twenty points of trust in one go. Offer him chocolate and he sniffs it and leaves it, which is the right answer for a dog and was put in on purpose. At fifty he lets you close enough to read the tag, and the game says so once: The name tag says Tyson. He tilts his head. At a hundred, one more fuss and he is yours. Tyson has decided you are his now. Loyal for life. From then on he follows. Sprint at a timid Tyson and he bolts at a proper run and holds it against you, slightly.
Three things in that list were wrong the first time. When he fled, he stood still. When you held out food, a timid dog never came any closer. And when he greeted you he did it while walking, so his feet skated across the pavement. The agent reported the first run as broadly working, which it was, and then went and fixed the three things that made it look like a game rather than a dog.
The flee was the interesting one. The agent had told him to run directly away from the player. On a terraced street, directly away from the player is very often somebody's back garden, behind a fence, and a dog cannot work out a route into a garden it cannot reach, so it did the next best thing and did nothing. He now picks a spot off to one side, and picks again if he stops moving.
By half six his trust was being saved with everything else in the game, and the save check restored all 160 fields exactly. By quarter past eight he had sounds: panting after a run, a lap at the water, a jingle from the tag at a trot, a growl if you charge him. One dog voice for all of it, deep, cut from free recordings. James listened through it and said the sound was good. He also said he looks cute, which is not in any of the acceptance tests.
Five hens and a shattered shape
The hens had started the day on the other side of the queue. There are five of them in a neighbour's back garden - three brown, two white Sussex - and the morning job was making them live like hens: wander, then at sunset walk the length of the run, up the ramp and in through the pop-hole, doors shut, and back out down the ramp at sunrise.
The first test in the running game at ten to one showed something else.

Each hen rendered as a giant shattered shape, metres tall, brown and white shards hanging over the terrace. The size readings on the asset said a normal 21 to 30 centimetres. So did the size of the placed actor. Every check the agent could run said the hen was hen-sized. Only the hen moving was wrong.
The agent did the useful thing first. It swapped the original chicken model from the animal pack onto the same hens in the running game, without touching any asset, and got a normal hen. That put the fault in the mesh, not in the behaviour. The mesh had been through Blender earlier in the week to make the birds look more like real breeds, and on the way back out the top bone of the skeleton had come out at a scale of 1, with every bone under it measured in centimetres. The pack's own skeleton has that bone at 100, with everything under it in metres. They come to the same shape standing still. The moment an animation moves that top bone, it moves it a hundred times too far.
The fix was to make the hen's skeleton match the pack's, bone by bone, parents first, inside the editor. Thirty-three bones. The agent's first plan, scale the top bone and divide every child by a hundred, would have double-scaled the lot, because the tool keeps each child where it is in the world and recalculates it for you. By ten to three all 33 matched, and the hens were hens again. They walked in at dusk and came out at dawn.
The agent also told James, plainly, that the pack's idle clip never puts the beak on the ground, so none of them were actually pecking. He asked for proper pecking. That took until nine. The new clip tips the body forward from the middle of the spine so the feet and tail stay planted, stretches the neck, and strikes four times before a look round. The beak lands within a centimetre of the grass at every strike and the toes do not move at all. James said they look realistic now.

His next note was that they walked into each other. By half nine a hen that comes within 38 centimetres of another steps aside, and the closest pair on the lawn held at 37.
Even the agents queue
None of this happened at once, because there is one editor and there were about six agents wanting it. They queue. The order was written into each handover in turn - hens, the estate, the darts, the dog, the monsters - and each agent handed the editor on with a message when it had finished. At one point James's instruction to the dog session was three words: join the queue. It did.
The pool tables came out of that queue as well. James wanted half of the snooker hall turned over to British pool - reds and yellows, the black last - with proper rules. The agent read the rulebooks and picked the one most British leagues play: a foul gives the other player a free shot and then a visit, with the cue ball placed anywhere behind the baulk line. The old pub version, two shots, is one switch.

Rather than write new physics, it ran the snooker physics on pool numbers, as a copy that inherits everything and changes only the table. Rockstar would have a team for this. He had a snooker table he had already finished. The rules were checked against a separate, simpler version of the same rules, written only to be argued with: 9,600 checks and 3,000 shots, and on the first run 20 of the first 1,378 came back wrong. A stalemate re-rack was still reporting the foul from the shot before it. One function fixed it. Then nothing failed.
At quarter to nine the test broke the pack, potted a yellow in the middle pocket and stayed on. A cue ball straight down into the same pocket came back as a foul: Player 2 to play - free shot. The cue picks up off the table with E and goes back down again.
Edward holds the chalk
The darts were in the pub, against Edward, the regular at the Slag & Slurry. Gamepad first, mouse as a backup. The board went on the back wall, left of the bar, near where he sits.
Late in the afternoon James had the better idea. In a real pub somebody has to keep the score, and it is usually whoever is not throwing. So after every visit Edward now gets up, walks to the board, pulls the darts out, turns to the chalkboard and writes the new score on it, a few characters a second, then goes back. In the first test he threw sixty and chalked 441.

Two faults turned up while building it, and both had passed a check first. The YOU and EDWARD labels came out as UOY and DRAWDE, because the text was facing the wall and the engine draws text from its own front. And the builder that rebuilds the darts graphs had been told to clear each graph first. It never cleared anything. Every delete had been failing with an error, and a line put in to tidy up errors had been throwing each one away in silence. The readback was clean. One graph had quietly doubled, from 68 nodes to 146. It was found by counting the nodes in it.
James's own go with a pad was put back to later in the evening and then left for another day. The agent said that was fine. Nothing else was waiting on it.
Four zebras and a puffin
Across the map, the new estate got its street furniture: 149 street nameplates, four zebra crossings with orange globes on striped poles at the kerbs, and one puffin crossing. He had once gone out photographing what he thought were pelicans and found they were puffins, so the agent was careful about which was which.

At seven the agent reported that the estate's roads did not actually reach the main roads. Every one stopped short, and every one sat 20 to 40 centimetres lower than the road it was meant to join. By five to eight there were eight proper junction mouths, with curved kerbs, give-way markings and the climb spread over about seven metres so nobody bottoms out. Two of them have a gap in the central reservation for traffic lights.
He was at his parents' by then. They usually get a playtest video on a Sunday. There was more than usual to choose from.
The fault
Unreal Engine 5.8 skeletal mesh explodes into giant shards in PIE but its bounds read normal
Each hen rendered metres tall as shattered shards over the street, but only when animated. Asset and actor bounds both read a normal 21-30 cm, so every size check passed.
Diagnostic that settled it: swapping the original pack mesh onto the same actors at runtime rendered a normal hen, so the behaviour graph was fine and the mesh was the fault.
Cause: the mesh had been round-tripped through Blender. The export gave the root bone scale 1 with centimetre child offsets; the pack's skeleton has root scale 100 with metre offsets. Identical at rest. The clips drive the root, so they moved it 100x too far.
The fix
Rebase the reference skeleton to the source pack's, top-down, inside the editor
With SkeletonModifier, parents first, set each bone's local transform to the source mesh's, commit and save. After a reload 0 of 33 bones differed.
The guard: SkeletonModifier.set_bone_transform(move_children=False) keeps each child's world transform and recomputes its local one, so "scale the root, then divide every child by 100" double-scales. And fix the Blender export to match the source hierarchy, or the next re-export brings the fault back.
The fault
Stray dog AI freezes instead of fleeing on a terraced street
The flee target was a point directly away from the player. On a terrace that is usually inside a fenced back garden, the path to it fails, and the dog stands still. Two related faults: a food lure only told a timid dog to hold position, so it never approached; and stance clips (greet, stretch) played while moving, so the feet skated.
The fix
Spread the flee point sideways and re-pick while stuck
Flee now picks a lateral point and picks again if the dog stops moving. A timid dog creeps in at a slink speed of about 39 cm/s when food is held. Stance clips play only when the dog is stationary.
The guard: in a dense street, test every "run away" target for reachability before trusting it.
The fault
Blueprint graph doubles on every rebuild while the readback stays clean
A Python builder cleared each graph before rewriting it. BlueprintTools.delete_node takes one argument, the node; it was called with two, raised TypeError every time, and a bare except: pass swallowed it. A parameterised function grew from 68 to 146 nodes with a clean readback.
The fix
Count node classes, and never swallow a builder error
A node-class census of the graph found the duplicates. The call now passes the node alone and any failure is printed.
Also: a TextRender reads from its own +X. Turned to face a wall at yaw 180 it rendered mirrored - "UOY", "DRAWDE". The labels now sit at yaw 0.
The kit
| Tool | Why this one |
|---|---|
| Blender, run headless | reshaped a free German Shepherd into a Staffie and solved the hen's peck against the real rig |
Unreal Engine 5.8 SkeletonModifier | rebased the hen skeleton inside the editor, bone by bone |
| A rules oracle in plain Python | 9,600 checks against the pool Blueprint found the re-rack foul |
| The snooker solver as a child Blueprint | pool physics without touching code that has crashed the editor before |
| Free recordings from Freesound | one dog voice for every bark, growl and whine |
Plain English
| Term | What it means |
|---|---|
| skeleton | The hierarchy of bones inside an animated model. Two models sharing a skeleton can share animation. |
| root bone | The top bone of a skeleton that every other bone hangs from; scale it wrongly and every animation that moves it is multiplied by the same mistake. |
| reference pose | The neutral stance a character model is built in, before any animation is applied. Seeing it in a finished shot means the animation is not running at all. |
| blend space | An animation asset that mixes several clips by a number such as speed, so an animal eases from a walk to a trot to a run instead of snapping between them. |
| montage | A one-off animation played over the top of whatever a character is already doing, such as a head tilt or a wave. |
| animation blueprint | The logic deciding which animation a character plays and how one blends into the next. |
| Blueprint | Unreal's visual scripting. Logic built by wiring boxes together with lines instead of typing code. This whole game is built in it. |
| child Blueprint | A Blueprint that inherits everything from a parent and changes only what it needs to - here, the snooker physics running on a pool table's numbers. |
| oracle | A second, simpler implementation of the same rules, written only to be argued with. The real one is run against it thousands of times, and wherever the two disagree, one of them is wrong. |
| game instance | The one object that lives for the whole time the game is running, across level changes; it is where values that must last, and be saved, are kept. |
| 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. |
| navmesh | An invisible map of walkable ground that characters use to work out routes. No navmesh, no walking. |
| zebra crossing | The British crossing with black and white stripes and a flashing orange globe on a striped pole at each kerb; there are no lights for traffic, and drivers must stop for anyone on it. |
| bellmouth | The flared end of a side road where it meets a main road, with curved kerbs so a car can turn in without mounting the pavement. |
Things we still need to fix tomorrow:
- James plays a frame of pool with the mouse and the pad, then the two pool regulars get names and their own games.
- The pool balls are silent; the snooker sounds port across next.
- James's go at the darts with a pad, then the aim and flick get tuned to it.
- Tyson's scratch clip is made and wants a moment to play in, sat at your side.
- A befriended Tyson reloads at his usual spot rather than next to you, and joins you again at the next meeting. Bringing him home properly is the next stage: the bowls at 6 Radworth Road, walks, play.
- Give-way signs on the estate, then a walk round the new junctions.