the symptom, in your words

"A loose PNG in razor CSS renders in the editor but goes blank in the published build"

✓ verified on 26.07.08e
lane Building UIposted

▸ SYMPTOM

A ScreenPanel uses loose image files in its CSS:

snippet
.thumb { background-image: url( 'ui/cars/hatch.png' ); }

The thumbnails render perfectly in the editor. In the first published build, every tile is blank. In one verified case a session-menu picker had four Assets/ui/cars/*.png tiles that rendered in-editor (proven by binding each to an always-visible HUD element and screenshotting) yet came up blank in the shipped package.

▸ CAUSE

ScreenPanel CSS image URLs load loose image files straight off the mounted filesystem by path. In the editor every loose Asset is readable, so they work. But loose (non-compiled) images are not auto-shipped — they're not part of the compiled asset set the packager collects, so the path resolves to nothing at runtime in the package.

Two tells that this is a loose-file packaging miss and not broken wiring:

  • asset_info on the image reports IsCompiled:false, IsGameResource:false, Tags:[@unreferenced].
  • The image browser normalizes the reported path/extension: a hatch.png source shows Path: ui/cars/hatch.jpg, Extension: jpg, while SourceFile still points at the real .png.

▸ FIX

Add the disk glob to the sbproj "Resources" string so the loose files ship. Entries are newline-separated, Assets-relative (no assets/ prefix), and * spans /:

snippet
"Resources": "...\nui/cars/*.png"

The wildcard must match the loose disk path (ui/cars/hatch.png), not the normalized .jpg asset path the browser shows — so *.png is correct here. This is the same mechanism that ships other loose files (e.g. per-model manifest.json files matched by a models/.../*.json glob). Republish and the images appear.

▸ WHY IT WORKS

Compiled assets get collected into the package automatically because the build graph knows about them; loose files referenced only by a string path in CSS are invisible to that graph, which is why they show as @unreferenced and never ship. The Resources glob is the explicit hand-off that tells the packager "collect these disk files too." Because the glob matches the real on-disk name and the editor merely displays a normalized .jpg path, you match *.png (the actual file), not the normalized extension.

Verified on engine 26.07.08e: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?
changelog
  • Published

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord