Build downloadable theme parks for the real world.
The DreamPark SDK is a Unity 6 project on GitHub. Clone it, open it, set a content ID, build your attraction, script gameplay in Lua, and publish from the editor — your build downloads to physical DreamPark venues from there.
Public on GitHub
Clone the repo and open in Unity 6. No approval gate to get started.
Lua-first scripting
XLua maps Unity's API 1:1, and scripts push over-the-air without rebuilding.
One-click publish
The editor's Content Uploader packages and ships your build to venues.
Best practices
Read this first — it's the short list that separates attractions that thrive at real venues from ones that don't:
- Write gameplay in Lua. XLua maps Unity's API 1:1 and
LuaBehaviourdoes everythingMonoBehaviourdoes — and Lua ships over-the-air, instantly. New C# has to be manually reviewed and waits for a future app release. Scripting in Lua. - Build for hand tracking and physical movement. Guests walk around a real room with their hands. Don't design around controllers, keyboard input, or stationary play — none of that exists at the venue.
- Design for 5 to 60 minute sessions. Most attractions sit somewhere in that range. Long onboarding, slow tutorials, and complex menus are friction in a setting where guests are paying for time.
- Whatever ships has to just work. Guests can't reset, restart, or troubleshoot. Test on real Quest 3 hardware before publishing.
- Keep builds lean. Use the Optimization tools and Manage Third Party Assets to strip out anything you're not using. Every megabyte downloads to every venue.
- No undisclosed data collection. Per the SDK Use Agreement, analytics, telemetry, or tracking inside your attraction must use the platform-provided analytics. Don't roll your own.
Overview
DreamPark is a chain of mixed-reality theme parks. Guests show up, put on a Quest 3 and a DreamBand wristband, and walk into your attraction in a real physical room. Your build downloads to the venue, runs on the headset, and earns you a share of every play.
The SDK is the framework you use to build those attractions. It's a complete Unity 6 project — clone it, open it, and your content lives under Assets/Content/. Everything else in the project is platform plumbing that keeps your build compatible with venue hardware: wristbands, headsets, payment kiosks, networking, and so on. The SDK is released alongside the main DreamPark app and you pull updates when we ship them.
Coming from at-home VR or indie? A few things are different in a real venue. Guests are paying customers playing in a shared physical room for somewhere between five minutes and an hour. They can't reset, restart, or troubleshoot — whatever ships has to just work, every time, for everyone. Best practices above covers the small set of things worth knowing up front.
Quick start
- Clone the SDK from GitHub. The repo is public — grab it and go. Open it in Unity 6.
- Set your content ID. On first launch, a setup popup asks you to pick a unique identifier for your attraction (e.g.
coincollector). This renames the starter folder underAssets/Content/for you. - Open
Template.unityunderAssets/Content/<your-id>/1. Scenes/. Press Play — you're in the starter scene. - Create your attraction. Drop an AttractionTemplate, pick a size, drag in props. More below.
- Script gameplay in Lua with
LuaBehaviour— it does everythingMonoBehaviourdoes, and releases instantly. More below. - Test on a Quest 3. Build to a Quest 3 or Quest 3S for real-hardware iteration.
- Publish. Open
DreamPark → Content Uploader, sign in with your developer account, fill in name/description/release notes/logo, and click Compile & Upload. More below.
Requirements
- Unity 6. The SDK targets Unity 6 specifically.
- A DreamPark developer account for the Content Uploader and publishing. Sign up here.
- Git. You'll clone the SDK from GitHub.
- A Meta Quest 3 or Quest 3S for testing on real hardware.
- macOS, Windows, or Linux all work for development.
Project structure
The project is one Unity 6 solution. Everything you build lives under Assets/Content/<your-content-id>/; everything else is the SDK and Unity itself. Hover the highlighted rows to see what each core piece does.
Your content is made of three pieces: a persistent Player, your Attractions (A_*.prefab), and their Props (P_*.prefab). Multiple content folders can coexist in one project — each is its own independent package, and the Content Uploader's dropdown picks which one to publish.
Set your content ID
The first time you open the project, the Content ID Setup popup walks you through picking a unique identifier for your attraction. The ID:
- Must start with a letter
- Can contain letters and numbers only
- Must be between 2 and 64 characters
The popup renames the starter folder from the template placeholder to Assets/Content/<your-id>/ and keeps Unity GUIDs intact so nothing in the scene breaks. Pick something short and final — this is the canonical ID used to publish your attraction.
If the popup ever reappears, it means the project doesn't have a valid content ID set. Fill it in again and you're back on track.
Create your first Attraction
Open Template.unity under Assets/Content/<your-id>/1. Scenes/. You'll see a blank arena — that's your canvas.
An Attraction is a prefab with an AttractionTemplate component on its root (naming convention: A_MyAttraction.prefab). The template auto-attaches a GameArea (the playable boundary that detects guests — and measures the playtime your revenue share is based on) and a MusicArea (an audio zone). Drop one into the scene, then pick a size from the inspector — they range from Micro (a few square meters) up to Jumbo, with a Custom option for anything in between.
The Attraction template includes inspector toggles to auto-generate floor and ceiling meshes, so you don't have to model them yourself unless you want to. When it's ready, save it as a prefab under Assets/Content/<your-id>/Prefabs/ — an HD preview is auto-generated for every attraction, so it shows up in the app with tile art automatically. Open A_TestAttraction in the starter project to see a working example.
Create your first Prop
Props are interactive bits between attractions — they let operators fill tight hallways with collectable coins, or add environmental detail around core attractions. A Prop is a prefab with a PropTemplate component on its root (naming convention: P_MyProp.prefab), which carries a category (Coin, Block, Hazard, Decoration, etc.) and a calibration Y-offset so the prop sits correctly on the floor at real venues.
Props also work inside your attractions: drag a prop prefab in, position it, and it's hooked in. Behind the scenes the SDK regenerates collision avoidance data (used for hand tracking and player movement) whenever you change the attraction or its props — you don't manage that yourself. HD previews are auto-generated for props too.
The starter project ships example props under Assets/Content/<your-id>/Prefabs/ — open P_Enemy and P_TestProp to see how working props are put together.
Customize your Player
Player.prefab (under Assets/Content/<your-id>/2. Features/) is the root player object, already placed and wired into the Template scene. It persists across attractions, so anything you attach to it survives scene loads. Use it for things that should outlive a single attraction — global score state, audio managers, park-wide systems — attached as LuaBehaviours and injected into your props.
About the DreamBand. The DreamBand is DreamPark's core in-game interface — it displays the guest's profile, Wi-Fi status, DreamPoints, and video recording across all content experiences, and it is not a developer-edited component. If you build UI for points, we recommend building around the band, not on top of it: diegetic world-space readouts on props, scoreboards in the room, effects near the wrist.
Scripting in Lua
Write your gameplay in Lua. All of it. The SDK is built around XLua, and there is nothing you can do in a MonoBehaviour that you can't do in a LuaBehaviour:
- XLua is a 1:1 map of Unity's API. Every Unity type, method, and property is reachable through the
CSnamespace:CS.UnityEngine.Vector3.up,CS.UnityEngine.Time.deltaTime,CS.UnityEngine.Object.Instantiate(prefab). If you know how to write it in C#, you already know how to write it in Lua — the call is the same, just prefixed. LuaBehaviourdoes everythingMonoBehaviourdoes. The same lifecycle (awake,start,update,ondestroy), the same physics callbacks (oncollisionenter,ontriggerenter), the same component access viaself.transform/self:GetComponent(...), plus inspector-injected references (GameObjects, AudioClips, other scripts) that appear as globals in your script.- Lua releases instantly. Scripts are data, not compiled code — they push over-the-air to live venues without an app rebuild. Guests pick up new behavior on their next session.
Add a LuaBehaviour component to any GameObject and point it at a .lua.txt file under Content/<YourGame>/Scripts/:
lua-- coin.lua.txt: a spinning coin any hand can collect
local rotateSpeed = 90 -- degrees / sec
function update()
self.transform:Rotate(CS.UnityEngine.Vector3.up * rotateSpeed * CS.UnityEngine.Time.deltaTime)
end
function ontriggerenter(other)
if other.tag == "Hand" then
sparkle:Play() -- injected ParticleSystem
scoreManager.add(1) -- injected LuaBehaviour on the Player
CS.UnityEngine.Object.Destroy(self.gameObject)
end
end
Avoid new C#. Custom C# scripts must be manually reviewed by DreamPark and only run on devices after they ship inside a future app release — expect a significantly longer path to release and slower iteration on every change afterward. Porting existing Unity content? Convert the gameplay scripts to Lua as you bring them in; most C# translates line for line. If you hit something that truly seems impossible in Lua, talk to us before writing C#.
Third-party assets
You'll bring in art packs, audio libraries, shaders, plugins, and the like from the Asset Store or external sources. Unity imports them into Assets/ThirdPartyLocal/ by default — that folder is gitignored and stripped from builds, so it's a safe staging area to experiment.
When you're actually using a third-party asset, move it into your content folder so it ships with your build. Don't shuffle files by hand — the SDK ships a tool that does it for you:
menuDreamPark → Manage Third Party Assets
This tool — Third Party Sync — scans your content folder for references, follows them to the third-party files those references point to, and moves them from ThirdPartyLocal/ into Assets/Content/<your-id>/ThirdParty/. It preserves Unity GUIDs so prefab and scene references don't break. The same sync also runs automatically as part of the Content Uploader's Compile & Upload flow, so you can let it handle the move on publish if you'd rather not think about it.
Why bother? Anything in ThirdPartyLocal/ doesn't ship in your build. Anything in your content folder's ThirdParty/ does. The sync tool draws that line cleanly.
Publishing
Publishing is one panel: DreamPark → Content Uploader. You'll use it for every release.
Fill in:
- Content ID — pick from a dropdown of the content folders in your project
- Name, description, release notes
- Logo image
Then choose an upload mode:
- All — full upload. Use for your first publish.
- Patch — incremental upload of just the assets that changed. Use for ongoing releases.
- Code — Lua-only push. Use when you've only changed Lua scripts and want a fast OTA update.
- Previews-only — refreshes the thumbnail and metadata without uploading content.
Hit Compile & Upload. A progress popup shows what's happening as the panel runs optimization checks, packages your build as Unity Addressables, and pushes it to DreamPark. Your attraction goes live to venues from there.
Revenue sharing is governed by your Revenue Sharing Agreement. The economics — what counts as revenue, how the waterfall splits, when you get paid — are explained in plain English here.
Updating the SDK
When DreamPark ships a new SDK version, the editor checks for it on launch and shows a small popup with release notes. You can also check on demand:
menuDreamPark → Check for SDK Updates
The update is delivered as a .unitypackage file. When you click Update Now, the editor downloads it and opens Unity's standard import dialog so you can review what's changing (and uncheck anything you've locally modified). Click Import and you're on the new version.
You can dismiss an update and keep working — it's not blocking. Per the SDK Use Agreement, the expectation is to update within 30 days so your builds stay compatible with current venue hardware and OS.
Optimization
The SDK ships dedicated tools to slim down your build before publishing. They live under DreamPark → Optimization:
- Texture Optimizer — finds oversized or unnecessarily large textures and offers one-click downsampling
- Material Optimizer — surfaces redundant or unused materials
- Audio Optimizer — flags uncompressed or oversized audio
- Animation Optimizer — trims expensive animation data
Run them before each publish. They make a meaningful difference to download size on real venue networks, and the Content Uploader will surface optimization warnings if you skip them.
Troubleshooting
The Content ID Setup popup keeps reappearing
The popup shows whenever the project doesn't have a valid content ID set. If you've already named yours and it keeps coming back, check that the content folder under Assets/Content/ still exists and the ID matches the format (starts with a letter, alphanumeric or underscore, 2–64 chars).
Login popup keeps coming back
The Content Uploader and SDK Update Checker need you to be signed in. If you keep getting bounced to the login popup, your session has likely expired — sign in once and it should hold. If it persists, check that your computer's clock is correct (session validation is time-sensitive).
"DreamPark/Troubleshooting" menu
The editor includes a built-in menu at DreamPark → Troubleshooting with one-click fixes for common issues: regenerating attraction previews, regenerating Lua codegen, cleaning addressables, fixing broken script references. Try those first.
Builds are huge
Usually traceable to unoptimized or unused assets in your content folder's ThirdParty/. Run the tools under DreamPark → Optimization to find the worst offenders, and use DreamPark → Manage Third Party Assets to make sure you're only shipping what you actually use.
Lua changes aren't picked up
If you've added a new .lua file or renamed something, Unity may need to regenerate the Lua bindings before the new script is visible. Run DreamPark → Troubleshooting → Regen Lua Codegen and Play again. For OTA pushes to live venues, the next guest session picks up the new Lua — no app rebuild needed.
Get support
The fastest place to reach us:
- Email community@dreampark.app for SDK and program questions.
- Use
DreamPark → Troubleshootingin the editor for common fixes. - See Revenue Share for economic terms.