Luna became Playworks — same lineage, new name

"Luna" was the name under which Unity's playable-ad creation toolkit first became widely known — a plugin for building interactive HTML5 ad units directly inside a Unity scene. Unity has continued developing that toolkit under the name Playworks/Luna, and most current documentation, editor menus, and support threads now refer to it that way. If your team set up a project a while ago, or a colleague handed down notes that still say "Luna," you haven't fallen behind on tooling — you're just using the older name for the same lineage of product.

That's why this page and our Unity Playworks/Luna alternative page cover the same underlying reality: the export process, the click-through conventions, and the packaging problem are identical regardless of which name is on the splash screen when you open the editor.

What Luna/Playworks actually builds — and what it leaves for you to do

Luna/Playworks does its job well: it takes your Unity scene, gameplay logic, and creative assets and compiles them into a working HTML5 playable, exported as a ZIP. That export runs correctly in a standalone browser preview. What it doesn't do — because it isn't designed to — is reshape that single export to satisfy seven different ad networks' seven different packaging rules at once.

Each network you might submit to has its own idea of what a "valid" playable looks like:

  • The click-through call is different everywhere. Google's exit call is ExitApi.exit(), Meta expects FbPlayableAd.onCTAClick(), Mintegral expects window.install() with an MRAID mraid.open() fallback, TikTok expects window.openAppStore() from its own Playable SDK, AppLovin and Unity Ads both expect MRAID 2.0's mraid.open(url), and Vungle's primary call is window.parent.postMessage('download','*') with MRAID open as its fallback. Ship the wrong call and the network can reject the creative outright, or worse, approve it with a dead CTA.
  • Self-containment rules aren't universal, but where they apply they're strict. AppLovin, Meta, Unity Ads, TikTok, and Vungle all prohibit external network requests entirely — every image, sound, and font has to already be inside the file, encoded, with nothing fetched at runtime. Google is the exception: it allows a short allowlist of Google-hosted libraries (Google Fonts, Google-hosted jQuery/CreateJS/Greensock, and its own ExitApi script) alongside local relative-path assets in a ZIP.
  • Output shape varies by network, not just by size limit. AppLovin, Meta, Unity Ads, and Vungle each want a single self-contained HTML file (one file, full stop). Google and Mintegral want a ZIP — but Google wants a flat archive capped at 512 files with an entry index.html and an orientation meta tag, while Mintegral wants the archive name, top-level folder, and HTML filename to all match, plus a working window.gameEnd() callback. TikTok wants its own index.html in the first-level directory alongside a config.json declaring orientation, plus its Playable SDK script — and it explicitly prohibits MRAID-style markup.
  • Size budgets are tight and consistent, but recommendations vary. Every network here caps at 5 MB, and Meta and Unity Ads specifically recommend staying nearer 2 MB. Assets that fit comfortably as external files during development can blow past that budget the moment they're properly inlined for a network that prohibits external requests.

None of that is a flaw in Luna/Playworks — it's simply outside its job description. The tool's job ends at "produces a working playable." Everything above is what happens between that export and a creative that actually clears review on a specific network.

Click-through call and packaging, network by network

NetworkClick-through callKey packaging rule
Google AdsExitApi.exit()Flat ZIP, ≤512 files, ≤5 MB, orientation meta tag required
MetaFbPlayableAd.onCTAClick()Single self-contained HTML, ≤5 MB (2 MB recommended), zero external requests
AppLovinmraid.open(url) (MRAID 2.0)Single HTML, both orientations supported, zero external requests, ≤5 MB
Mintegralwindow.install() → MRAID fallbackArchive name, top folder, and HTML filename must match; needs window.gameEnd()
TikTokwindow.openAppStore() via Playable SDKindex.html + config.json declaring orientation; no MRAID markup, no external requests
Unity Adsmraid.open(url) (MRAID 2.0)Single HTML, ≤5 MB (2 MB recommended), zero external requests
Vungle (Liftoff)postMessage('download','*') → MRAID fallbackSingle HTML, zero external requests, ≤5 MB

Where PlayableKit fits — and where it doesn't

To be direct about what this product is: PlayableKit does not replace Luna/Playworks, and it can't build your playable for you. You still design the scene, write the gameplay logic, and export the ZIP inside Unity exactly as you do today, whether your install still says "Luna" or has moved to "Playworks/Luna." PlayableKit picks up at the step after that export exists — it's the automation for adapting one Luna/Playworks export into a compliant package for each network you're targeting, not a substitute for the engine tool itself.

In practice: upload the same export ZIP once, select the networks you're shipping to, and PlayableKit generates a separately packaged creative per network — the correct click-through call wired in, assets embedded and encoded to that network's rules, and the file/folder shape it expects, built from that one source export.

StepManual processWith PlayableKit
Click-through wiringHand-write ExitApi.exit(), MRAID, SDK, or postMessage calls per networkApplied automatically per network
Asset embeddingManually inline every asset as a data URI for AppLovin, Meta, Unity Ads, TikTok, VungleAutomatic base64/base122 encoding
Package shapeRename files/folders for Mintegral; hand-write TikTok's config.json; build Google's flat ZIPGenerated to spec automatically for each network
Size/compliance checkUpload and wait for network review to find outFree validator gives a pass/fail report per network before you submit
Worth knowing: if you just want to check whether your current Luna/Playworks export has an obvious structural problem — a missing entry file, a broken inline script, missing engine assets — before doing anything else, PlayableKit's Playable Ad Validator checks that for free with no signup.

A note on pricing

Unity doesn't sell Playworks (or the older Luna toolkit) as a standalone purchase — it's bundled somewhere inside Unity's broader engine subscription tiers, and those tiers change often enough that repeating a number here would likely be wrong by the time you read it. If cost is part of your decision, unity.com is the only place to get a current figure.

PlayableKit's own pricing, by contrast, is simple and posted in one place: Starter runs $400/mo, Studio $560/mo, Scale $800/mo, and Enterprise is custom-quoted for larger teams. See the full pricing breakdown for what each tier includes.

Is switching your export workflow worth it?

If you're only ever shipping to a single network, hand-adapting one export is a one-time cost you can absorb. The math changes once you're maintaining the same creative across three or more networks, or shipping new variants often enough that re-doing the click-through wiring, asset encoding, and packaging by hand — for the same underlying build, over and over — becomes the actual bottleneck in your release cycle rather than the creative work itself.