What Playworks/Luna actually does — and doesn't
Playworks/Luna builds a working playable from your Unity scene and exports it as a ZIP (on a typical setup, that's ProjectRoot\LunaTemp\stage4\create-hub). That export runs correctly in a browser. What it doesn't do on its own is satisfy every ad network's specific packaging rules at once — Major ad networks each have their own entry-file conventions, size caps, click-through APIs, and (in several cases) a hard requirement that every asset be embedded as base64/base122 data with zero external requests.
That gap is where the actual manual work lives, and it's the same work regardless of which engine or export tool produced the original build.
What adapting a single export for multiple networks actually involves
- Click-through wiring — Google expects a
clickTagvariable plus its own ExitApi script; AppLovin and Unity Ads expect an MRAIDmraid.open()call; Vungle's primary CTA iswindow.parent.postMessage('download','*')with MRAID open as a fallback; Mintegral expectswindow.install(); TikTok expectsopenAppStore()from its own Playable SDK; Meta expectsFbPlayableAd.onCTAClick(). None of these are interchangeable — shipping the wrong one is a common cause of a creative being rejected outright. - Asset encoding — AppLovin and Meta require a single self-contained HTML file with zero external requests, which means every image, audio clip, and font has to be inlined as a data URI or an encoded blob decoded at runtime, not referenced by a relative path.
- Size limits — most networks cap creatives at 5 MB, and a handful specifically recommend staying near 2 MB. A build that's fine for one network can be well over the limit for another once its assets are properly embedded rather than loaded on demand.
- Package shape — Mintegral specifically wants the archive name, top-level folder, and HTML filename to all match; TikTok wants a first-level
index.htmlplus aconfig.jsondeclaring orientation; Google wants an orientation meta tag and a flat ZIP under 512 files.
Doing this by hand for one network is tedious but manageable. Doing it correctly for five or six networks from the same source build, every time you ship a new creative, is where teams either build internal tooling or start looking for something else.
Where PlayableKit fits
PlayableKit doesn't replace Playworks/Luna — you still build in Unity exactly as you do today. It picks up right where Playworks/Luna leaves off: upload the same Luna/Playworks export ZIP once, and PlayableKit produces a separately packaged, network-compliant creative for each network you select — clickTag/MRAID/SDK wiring, asset encoding, and package shape all handled per network's actual rules, from that one source build.
| Step | Manual process | With PlayableKit |
|---|---|---|
| Click-through API per network | Hand-write clickTag / MRAID / SDK calls for each target | Applied automatically per network |
| Asset embedding (AppLovin, Meta) | Manually inline every asset as a data URI | Automatic base64/base122 encoding |
| Package shape (Mintegral, TikTok) | Manually rename files/folders, hand-write config.json | Generated to spec automatically |
| Size/compliance check | Upload and wait for network review to find out | Free validator plus a pass/fail report per network before you submit |
Is switching worth the effort?
If you're only ever shipping to one network, probably not — the manual work is a one-time cost per creative. It starts paying off the moment you're maintaining the same creative across three or more networks, or shipping new variants often enough that re-doing the per-network adaptation by hand becomes the actual bottleneck in your release cycle.