"Unity" and "Unity" are not the same product
Unity Playworks/Luna (formerly Luna) is a build tool that lives inside the Unity Editor. It takes your Unity scene and exports it as a playable ad — a folder or ZIP containing an HTML entry point plus supporting assets, typically landing at ProjectRoot\LunaTemp\stage4\create-hub. It has no opinion about where that export eventually runs.
Unity Ads is a completely separate product: an ad network and mediation platform that serves ad creatives — video, static, and playable — inside other apps, and pays out when your ad drives installs or engagement. It has its own packaging rules for any playable creative submitted to it, and those rules don't care what tool built the creative. A playable exported by Playworks/Luna, a different engine, or hand-coded HTML all have to satisfy the exact same Unity Ads requirements.
So "exporting Unity Playworks/Luna to Unity Ads" doesn't mean pointing one Unity tool at another. It means taking a Playworks/Luna export and repackaging it to satisfy Unity Ads' submission spec — a separate, unrelated checklist. That's the actual task this page covers.
What Unity Ads requires from a playable creative
Unity Ads' playable spec is strict and specific. Every point below is a real submission requirement, not a suggestion:
| Requirement | Detail |
|---|---|
| Output format | A single, self-contained HTML file — not a ZIP, not a folder of linked assets. |
| Size limit | 5 MB maximum. Unity Ads recommends staying near 2 MB for reliable load times. |
| MRAID version | MRAID 2.0 is required. The creative must implement the MRAID interface Unity Ads' player expects. |
| External requests | Prohibited entirely. Every image, audio clip, font, and script must be embedded directly in the HTML — no network calls out. |
| Click-through | The CTA must call mraid.open(url). There's no alternate API Unity Ads will accept for click-through. |
| MRAID ready state | The creative must wait for the MRAID ready event before making any MRAID API calls or rendering layout decisions. |
| Audio | No auto-playing audio before the user interacts with the ad. |
Miss any one of these and the creative either fails validation on submission or — worse — passes review but misbehaves in the wild (a CTA that does nothing, a layout that breaks before MRAID initializes, audio that plays before a user has tapped anything).
Why a raw Playworks/Luna export doesn't satisfy any of this yet
A stock Playworks/Luna export is built to run correctly in a browser, full stop — it isn't built against Unity Ads' spec, or any single network's spec. In practice that export is usually a folder of multiple files with relative asset paths, no MRAID calls anywhere in it, and no ready-state gating around interactive logic. Every requirement in the table above is something that export doesn't yet do:
- Single file: Playworks/Luna exports as a set of files referencing each other by path, not one self-contained document.
- Embedded assets: images, audio, and fonts are separate files the export loads at runtime — the opposite of "no external requests."
- MRAID wiring: there's no
mraid.open()call in a generic export, because Playworks/Luna doesn't know in advance which network — if any — will need MRAID. - Ready-state gating: without a wait for MRAID's ready event, any interaction logic that fires immediately on load can run before Unity Ads' player has finished initializing the ad.
None of this is a defect in Playworks/Luna — it's simply out of scope for a build tool that has to stay agnostic about which of seven very different networks (Google Ads, Meta, AppLovin, Mintegral, TikTok, Unity Ads, Vungle) the export eventually ships to.
How PlayableKit handles the Unity Ads packaging automatically
PlayableKit doesn't touch how you build in Unity — you still use Playworks/Luna exactly as before. It picks up at the export: upload the Playworks/Luna ZIP once, select Unity Ads as a target, and PlayableKit produces a Unity Ads-compliant single HTML file built to that spec specifically.
| Requirement | Manual process | With PlayableKit |
|---|---|---|
| Single self-contained file | Manually merge every asset and script into one HTML document | Generated automatically from the Playworks/Luna export |
| Asset embedding | Hand-encode every image, audio clip, and font as a data URI or blob | Automatic base64/base122 encoding of all resources |
MRAID 2.0 + mraid.open() | Write the MRAID interface and wire the CTA by hand | Injected automatically for the Unity Ads target |
| MRAID ready-state gating | Manually wrap interaction logic behind a ready listener | Handled as part of the same packaging step |
| Size / autoplay-audio compliance | Upload and find out during Unity Ads review | Size checker and validator flag issues before you submit |
Because Unity Ads, AppLovin, Meta, Mintegral, TikTok, Google Ads, and Vungle all have distinct — and sometimes contradictory — click APIs and packaging shapes, PlayableKit builds a separate output per network from the same source export rather than trying to produce one file that satisfies all of them. The Unity Ads build gets Unity Ads' exact rules; nothing borrowed from another network's spec ends up in it.
The practical workflow
- Build and export your playable in Unity Playworks/Luna as usual — you'll get a ZIP export.
- Upload that ZIP to PlayableKit and select Unity Ads as a target network (along with any others you're shipping to at the same time).
- PlayableKit outputs a single, embedded, MRAID 2.0-wired HTML file sized for Unity Ads.
- Run it through the validator and size checker to confirm it's under the 5 MB cap (ideally near 2 MB) and free of autoplay audio.
- Upload the resulting file directly to your Unity Ads dashboard.
If you're also targeting Mintegral or TikTok from the same Playworks/Luna export, the process is identical — just add those networks to the same upload. See the Mintegral-specific and TikTok-specific walkthroughs for what changes in their packaging rules.