Why this happens

A Playworks/Luna export isn't one flat bundle — it's an index.html, an engine/ folder with the runtime scripts, an assets/ folder, and (in single-HTML/self-contained builds) a cache/<id>/ folder containing scripts.js, jsons.js, and blobs.js — Luna's own cache system, which already knows how to embed audio and binary blobs via window.sounds/window.blobs and its decompressString/decompressArrayBuffer helpers (brotli-compressed, base64 or base122-encoded). Nothing about audio or blobs needs special handling on top of that — Luna does it natively. Assets go missing when one of these pieces doesn't line up with what the final package expects:

  • A relative-path asset was never actually written into engine/. In folder-mode output (Google's ZIP, Mintegral's nested folder), the export still references files by relative path. If Playworks/Luna exported an incomplete engine/ or assets/ tree — a texture atlas or audio file the build referenced but didn't emit — that reference stays broken no matter how faithfully it's copied into the network package. This is a source-export gap, not a conversion-step gap.
  • A cache manifest entry exists, but the payload never landed. Luna's jsons.js can list a sound or blob key that blobs.js never actually populated — usually from an interrupted or partial Unity export. The cache scripts still get inlined verbatim; window.sounds/window.blobs then has a hole at runtime, and that one asset silently fails to play or render even though everything else in the same cache works.
  • The file extension isn't one the media inliner recognizes. Direct <img>/<video> references in the export's own markup (outside Luna's cache system) get inlined by extension — currently .png, .jpg, .jpeg, .webp, .gif, and .mp4. A reference to an extension outside that list (an unusual video codec's container, for example) is left as a relative path with nothing behind it once the file is embedded, and self-contained networks like AppLovin and Meta allow zero external requests — so that reference is dead on arrival.
  • A decompression mismatch on the cache payload. The single-HTML pipeline rewrites every decompressString(...)/decompressArrayBuffer(...) call it recognizes, decompressing the original brotli payload and re-encoding it as base64 so it survives every network's serving layer. If a cache script was hand-edited, produced by a mismatched Luna version, or uses a call shape the rewrite doesn't match, that payload is left in its original encoding — and the runtime that expects the rewritten form fails to decode it, so its assets never resolve.
  • Wrong cache ID selected when a build has more than one. Playworks/Luna can leave multiple numbered folders under cache/ from previous builds. Pointing a conversion at the wrong one pulls in scripts, JSON, and blobs from a different build than the one actually referenced by index.html, producing assets that don't match what the visuals expect.

How to diagnose it

Before assuming it's a conversion problem, check the source export itself. Playable Kit's free Playable Ad Validator checks a Luna/Playworks export or a converted package for exactly this class of issue — a missing entry file, an incomplete engine/ tree, a cache folder missing one of its three required files, or a broken inline script — before you spend a review cycle finding out from the network instead. Run it on the original export first; if the problem exists there, no converter can fix it.

What's handled automatically vs. what stays a source-export fix

CausePlayableKit's conversionWhat you still need to fix
Asset never written into engine//assets/Copies exactly what's in the exportRe-export from Unity/Playworks/Luna with the asset included
Cache manifest entry with no matching blob/sound dataInlines the cache scripts as-isRe-export the affected cache; the hole exists upstream
Unsupported image/video extensionInlines every extension in the supported set automaticallyConvert the asset to a supported format (.png/.jpg/.webp/.gif/.mp4) before export
Cache decompression/encoding mismatchRewrites recognized decompressString/decompressArrayBuffer calls to network-safe base64 automaticallyAvoid hand-editing cache scripts; re-export with a consistent Luna version
Ambiguous or wrong cache IDLets you pin a specific cache ID for the conversionConfirm which cache folder your current build actually uses
Worth knowing: if the same asset is missing across every network you convert to, the export itself is the common factor — check it with the validator before touching per-network settings. If only the self-contained networks (AppLovin, Meta, Unity Ads, Vungle) are missing an asset that shows fine in Google's ZIP output, that's usually the unsupported-extension case above, since folder-mode output doesn't need every asset inlined.

Missing assets are also worth ruling out alongside package size — an asset that fails to embed cleanly is sometimes symptomatic of a build that's already over a network's cap. If your export is also close to or over the 5 MB (or 2 MB recommended) ceiling, see what to do when a Unity Playworks/Luna build is too large.