Second Chance GazetteDevlogToken Use

Two Bright Readings

unreal-engineblueprintlightingexposurestreet-lampsweatherlightningblenderfbxuvumgwidget-componentinteractionmulti-agent

One in the morning

Saturday had finished at one in the morning. Anthropic had given everyone an extra usage reset with the launch of Opus 5.5, and James had spent the night using as much of it as he could, so Sunday started at nine. Two sausages, beans, an omelette and a coffee.

He went to the gym and ran. By the time he got back it had rained hard enough to cancel the barbecue his parents had been hoping for. They were home from Rotterdam, three weeks with his brother and the new baby, and dinner was moving indoors.

Before he left he gave Claude Code Opus 5.5 a list, and the list was about the dark. The street lamps came on too late. A storm needed lightning. The petrol pumps, which had been scenery for a month, needed to work. The work was split across several sessions, and by the evening seven or eight of them were sharing one open editor, taking turns to press play by sending each other messages.

That is the argument this entry makes, and it is the British one. GTA 6 is set in a sunny version of Miami. Second Chance is set in a Midlands town at the end of September, which means the question of when the street lamps come on is not a small one. It gets dark before tea. It rains on the barbecue. Rockstar have people for this. James had a Sunday, with a Sunday dinner in the middle of it.

Coming on too late

His complaint was specific. The lamps in Radworth came on at a fixed point in the sun's descent, and by then it was already too dark to see the road. Late at night the game was unplayable. He asked for them to work the way real ones do: on the light, not the clock, and early enough that a player can still find the kerb, and the jitty at the end of the terrace.

The agent read the lamp Blueprints before it touched them, and came back with a finding that changed the job. Moving the switch-on earlier, it said, would change nothing the player could see. The game pinned its camera exposure to daytime until the sun was two degrees above the horizon, so the whole of dusk was being metered as if it were noon. A lit lamp throws tens of lux onto a pavement. Under a daytime exposure that sits about seven stops below anything the screen shows. The lamps had been coming on. They had been invisible.

So there were two jobs, and the agent did them in the order the builder scripts on this project always run: VARS first, then the logic. VARS is its shorthand for variables, the named values a Blueprint keeps hold of - a speed, a cash total, a flag saying the lamp is on. James had heard the word enough over two days to ask what it meant. Say it to his dad and he hears VAR, the video referee, because his dad is a Forest fan. It had come up again that afternoon.

Each lamp now carries its own photocell. Every fifteen seconds it reads how much sunlight is reaching the street, and when that drops past a threshold the lamp comes on. The threshold is nudged slightly for every lamp by its position, so a street does not snap on at once. It comes on in a ripple, the way a real one does. The camera's exposure listens to the same reading and starts adapting as the light goes, one stop gained for each stop the sun loses, which is what the lamps needed to be visible at all.

A red-brick terraced street at night seen from the middle of the road, lit orange by a sodium street lamp on the right. Wheelie bins stand on both pavements, the upstairs windows glow yellow, the yellow centre line runs away between the houses and the sky above is black with a few stars.
Limekiln Close at 11pm, all fifteen lamps within 80 metres on. The bins are out.

There was one detail the agent put in for a reason that belonged to a different session. A lamp goes on after a single dark reading but only goes off after two bright ones. The weather system brightens the sun thirteen times over for a lightning flash, and without the second reading every lamp in a storm would flick off and back on with each strike.

In play, standing on Radworth Road with 56 lamps in range, it held. Just after ten in the morning, in rain, none were on. Jumped to twelve minutes to eight in the evening, all 56 were. At seven the next morning, after two bright readings, all 56 were off again. On a clear midsummer evening they now come on between 20:25 and 20:39 instead of all at once at 20:57, and under heavy rain from about seven.

Then James asked for five screenshots of the streets at night, and the shoot found the next problem. Along the horizon, behind the trees on three of the five streets, sat hard white shapes that had no business being there. A trace along one sight line hit the primary school at 248 metres. The agent logged it as unproven and did not touch it. The graphics card was reading 7.35 GB of its 8 before anyone pressed play, so the shots were taken at Medium.

Dinner

His parents' house, BBQ pork cooked indoors, veg and gravy. Mr Bean on the telly. His parents had had a good time in Rotterdam. He had been reading an argument on X that morning, artists on one side and AI on the other. That can wait.

When he got back to the desk the lamps were built and the lightning was half done.

Out of a dark cloud

The lightning had a rule before it had a mesh. James had laid it down early: lightning on a sunny day is extremely rare, it comes out of a dark cloud. So a visible bolt only appears when the cloud cover is at least nine tenths and the rain is heavy, and the channel starts 400 metres inside the cloud deck. Strikes come every four to twelve seconds in a full storm. Near ones, from 150 metres to two and a half kilometres, are drawn. Each strike plays its own thunder at the speed of sound, so one 3.49 km away rumbles about ten seconds after the flash.

The bolts themselves were built in Blender, eight of them, with the brightness of each branch packed into a spare set of texture coordinates so one material could light the main channel hard and the forks softly. The first render test drew nothing at all. The mesh imported at the right size. The material compiled. Every readback the agent took came back green, and there was no bolt.

It took a probe script to find out why. Somewhere between Blender, FBX and Unreal, the vertical texture coordinate is turned upside down, so a value of 1 arrives as 0. The main channel, the brightest part of the bolt, was being told to emit nothing. One subtraction in the material fixed it.

The second fault was bigger and easier to see.

A terraced street at night in rain with a jagged white lightning bolt coming down towards a church spire at the far end. The road, pavements, window sills and every upward-facing ledge are lit flat white, so the street looks covered in snow.
The flash as first built. It is not snowing. Every surface that faces the sky has been lit white from 312 metres up.

The flash that goes with each strike is a point light, and the agent had placed it twelve per cent of the way up the channel. On a bolt 2.6 km long that put it 312 metres above the street. From there it lit only what faced upwards: roofs, sills, the tops of walls, and the wet road, which is glossy enough to mirror it. The street looked as though it had snowed. It was gone midnight.

The same terraced street at night in rain, the same lightning bolt coming down towards the church spire, but now the light falls on the house fronts facing the strike. The road is dark and wet with puddles, windows glow warm yellow and a bookmaker's sign stands on the left pavement.
The same strike with the flash 60 metres up the channel. Now it lights the fronts of the houses that face it.

At 60 metres the light fell on the house fronts instead. The agent capped the height there, and wrote the fix into the build at 00:34. The fixed version is written and is next to be seen in play.

How bright the flash should be turned out to be something stills cannot answer. The agent shot it at 40 million candela, then four, then two, then 300,000, and the four frames came back nearly the same. The camera's auto exposure had re-adapted in the seconds between the setup and the shot. A real flash lasts under three quarters of a second, too short for the eye to adapt, so a near strike at the built strength would white out the whole screen. That one goes to James, in play, in real time.

Twelve times brighter

The pumps were the other thing working that evening. Radworth Services has eight of them and 48 nozzles, unleaded in green, diesel in black, super in yellow, at 144.0p, 149.0p and 158.0p a litre. Lift one with E and the hose pays out from 120 cm to 380. Walk away with it and it stops you three and a half metres from the pump. U puts it in the car's filler, U again starts it, and it pumps at 1.2 litres a second: 24.73 litres in 20.61 seconds cost £35.61, and the player's cash went from £500 to £464.39. The wrong grade does not fit. The nozzle bumps off the filler and there is no message, because a real one does not come with one either.

There were no drivable cars on the map to test with, and scripts cannot put one into a game that is already running. So the agent put two unsaved test cars on the forecourt in the editor, a petrol and a diesel, played, and took them away afterwards. Mid-fill on the diesel it drove the car six metres. The pump stopped, billed £11.56 for the 7.76 litres already in the tank, and the nozzle sprang back to its holster.

The screen was the fault.

A first-person view of a white petrol pump with three nozzles in their holsters and a green nozzle held in the player's hand at the bottom right. The pump's display panel is almost black, the words UNLEADED and a zero price only just visible.
The pump in play with the nozzle lifted. The display is working, and almost black.

The display is a widget component: a piece of ordinary game interface stuck onto the pump as a screen. The material it was drawn with reacts to the lights around it, and a pump under a forecourt canopy is in shade. The text was there and correct, and dark grey on black. The agent turned up the widget's tint in the running game. Twelve times was readable. Twenty-five was barely any brighter.

The same first-person view of the petrol pump, now with the display readable in green: UNLEADED above a price of zero pounds and zero litres. The player holds the green nozzle at the bottom right and the forecourt canopy is behind.
Tint at twelve times. Readable, and a stopgap.

It baked in twelve and wrote down that the proper fix is a material that ignores the lighting altogether, the way a real screen does. The plan is for an attendant to fill the car for you in the daytime. At night it is self-service.

The storm test finished at fourteen minutes past midnight. It was Monday by then.

The fault

Street lamps switch on at dusk but the street is still black in Unreal Engine 5.8

The lamps switched on from the sun's angle, and moving that earlier would have changed nothing. Exposure was pinned to the daytime value (EV100 8.0 to 8.8) until the sun was 2 degrees above the horizon, so dusk was metered as noon. A lamp's tens of lux sit about 7 stops under that. The lamps were on and invisible.

The fix

Switch the lamps on light level, and let the exposure follow the same reading

Each lamp reads the lux on the street every 15 s: sun intensity × the sine of its elevation. On below a threshold, off only after two bright readings in a row, so a lightning flash (sun ×13) cannot blink it off. A fixed per-lamp bias of 0.85 to 1.12 makes a street light in a ripple. The night post-process weight now also rises with lost light, one EV per stop past the first, capped at 3.7 EV.

The guard: a light that is on is not a light you can see. Check exposure before moving a switch-on time.

The fault

Lightning bolt mesh from Blender imports invisible in Unreal Engine 5.8

Brightness was packed into a second UV channel's V. Blender to FBX to Unreal flips V (v becomes 1 - v), so the main channel, brightness 1, arrived as 0 and emitted nothing. Size, material and compile all read back green. U is untouched.

The fix

Read any value packed into V as 1 - V

One subtraction in the material's emissive expression. Any data packed into a UV's V needs 1 - v after this import path.

The fault

Lightning flash point light turns every roof and road white like snow

The flash sat 12 % up a 2.6 km channel, 312 m above the strike, so it lit only upward faces. A wet road at roughness 0.02 mirrored it.

The fix

Clamp the flash to 60 m along the channel

Flash position = strike point + channel × the smaller of 12 % and 60 m. Short bolts keep 12 %. Judge intensity in real time: auto exposure re-adapts between setup and a still, so 40 M and 300 k candela shot alike.

The fault

WidgetComponent screen text almost invisible on a 3D object in Unreal Engine 5.8

The pump display used Widget3DPassThrough_Masked_OneSided, which is lit. Under a canopy the correct text rendered dark grey on black.

The fix

Tint the widget ×12 now, an unlit widget material next

TintColorAndOpacity ×12 is readable; ×25 is barely brighter. The real fix is an unlit, emissive widget material. Also: in 5.8 Python, widget_space, draw_size and two_sided are setters (set_draw_size), not properties.

The kit

ToolWhy this one
Claude Code Opus 5.5seven or eight sessions sharing one editor, taking turns at PIE by message
Unreal Engine 5.8Blueprint lamps, weather, strike and pumps, all tested in PIE
Blenderthe eight lightning bolt meshes, with brightness packed into a UV channel
A UV probe scriptproved the V flip when every other readback was green

Plain English

TermWhat it means
variableA named value a Blueprint keeps hold of - a speed, a cash total, a yes/no flag saying the lamp is on. Shortened to "vars" in the agent's reports, and a builder script's VARS step is the stage that creates them before any logic is written.
BlueprintUnreal's visual scripting. Logic built by wiring boxes together with lines instead of typing code. This whole game is built in it.
photocellA small light sensor on a street lamp that switches it on when the daylight fails and off when it returns, instead of on a clock. The lamps in Second Chance each have a simulated one.
exposureHow bright the virtual camera treats the scene, like a real camera's aperture and shutter. A higher EV100 number darkens the picture. This project pins it per building so a room does not slowly brighten while you stand in it.
debounceWaiting for a reading to stay the same for a moment before acting on it, so one freak reading - a lightning flash - does not flick a lamp off and on.
post process volumeA box in the level that changes how the final image looks inside it - exposure, colour, contrast.
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.
UVThe flat pattern that says which part of a 2D image lands on which part of a 3D model. Wrong UVs mean the texture arrives stretched or in the wrong place.
FBXThe interchange file format used to move models and animation between Blender and Unreal.
emissiveThe part of a material that gives off light - a screen, a bulb, a neon sign.
point lightA light that shines out in every direction from a single spot, like a bare bulb. Where you put it matters as much as how bright it is.
candelaA unit of how bright a light looks from one direction. A candle is about one; a lightning strike is millions.
widget componentA piece of on-screen interface, like a readout or a menu, pasted onto an object in the 3D world so it shows up as a screen on that object - a pump display, a till, a phone.
lit materialA lit material reacts to the lights around it and goes dark in shadow; an unlit one shows its own colour whatever the lighting, which is what a glowing screen needs.
VRAMMemory on the graphics card. This project has 8 GB of it, and that ceiling shapes most of the decisions in the devlog.

Things we still need to fix tomorrow:

  • James watches a near strike in play and picks the flash strength.
  • See the 60 m flash in play, then the flicker.
  • The sky stays black in a strike. The whole deck going lilac needs its own path.
  • Find what draws the white shapes on the night horizon, then reshoot two of the five streets.
  • A look at dusk in play: is 20:15 to 21:30 readable?
  • Fill a car with less money than the fuel costs.
  • The unlit screen material for the pumps, and the thin white line along the screen's top edge.

← 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