Manual

Export & Packaging

One click from project to standalone game — profiles, platforms, the hpak archive and mod support.

One click

How Export Works

Build ▸ Export Project… turns a project into a standalone game: the game runtime plus your assets cooked and packed into a single .hpak archive. The export runs asynchronously with a live build log; you keep working while it packs.

Project Content, scenes, graphs, scripts, config
Translate HorizonCode Every graph → a native C++ class; graphs that fail validation ship interpreted
Compile C++ CMake + host toolchain build HorizonCodeGen.dylib / .dll / .so
Cook & Pack Bake meshes, textures, shader variants & binary scenes; compress, encrypt, reuse unchanged entries
.hpak + Runtime Archive + game executable with the pak key embedded (re-signed on macOS)
Standalone Game Double-clickable — folder, .zip or macOS .app bundle

Cooking bakes assets into their runtime form — mesh vertex buffers, texture compression, precompiled material shader variants for the target backends, baked particle shaders — and rewrites all asset references as UUIDs so nothing resolves by fragile file paths at runtime.

Presets

Export Profiles

Exports are driven by named profiles stored in the project file — every project starts with Development (uncompressed, mods enabled) and Shipping (compressed + encrypted). Profiles are edited right in the export dialog and saved back with Save / Save As.

SettingEffect
Output Directory Defaults to <Project>/Export/<profile>.
Startup Scene The scene the game boots into (defaults to the open scene).
Target Platform Host / Windows / macOS / Linux — see below.
Compress assets zstd (or LZ4HC) per-asset compression.
Encrypt assets AES-256-GCM per-entry encryption — see Encryption.
Enable mod support The shipped game mounts overlay paks from a Mods/ folder.
Incremental packing Unchanged assets are reused byte-for-byte from the previous export.
Compile HorizonCode Translates all graphs to native C++. Compiler →
Exclude patterns Content-relative globs (e.g. Debug/*, *_test.hasset) left out of the pak.

Cross-platform

Target Platforms

A profile targets Host (the machine you're on) or cross-targets Windows, macOS or Linux using the per-platform game runtimes distributed with the editor. On macOS the export can produce a signed, double-clickable .app bundle — executable and libraries in Contents/MacOS, the pak and config in Contents/Resources, with a generated Info.plist and code signature.

Python projects automatically bundle the Python runtime and standard library with the game, so it runs on machines without a Python install.

The archive

The hpak Archive

.hpak is the engine's pack format (version 2): a table of contents indexed by asset UUID, followed by the compressed data blocks. Everything the game needs goes in — every cooked asset, all scenes in compact binary form, the GameInstance graph, a scene index, and a path index so assets referenced by path from scripts (for example widgets created with createWidget("UI/HUD")) resolve too.

  • Per-entry compression — zstd or LZ4; small or incompressible entries stay stored.
  • Integrity — a TOC hash is verified at mount and every entry carries a content hash checked on read, so corrupted files fail loudly instead of glitching.
  • Patch-friendly — archives support overlay mounting (the basis for mods and patches).

Protect

Encryption

With Encrypt assets on, every entry is encrypted with AES-256-GCM (a unique nonce per entry, with an authentication tag that makes tampering detectable). The key is generated at export and embedded into the game executable — on macOS the binary is re-signed after patching — so no key file ships next to the pak.

Honest scope: since the key necessarily ships inside the game, encryption is asset obfuscation — it keeps honest people honest and protects against casual extraction, but it is not a security boundary.

Fast re-exports

Incremental Packing

Each export writes a manifest next to the pak. On the next export, entries whose content and settings are unchanged are copied byte-for-byte from the previous archive — no recompression, no re-encryption (the previous key is reused so encrypted entries stay identical). Change one texture and only that texture repacks. Changing the codec or encryption settings invalidates the cache automatically.

At runtime

Streaming at Runtime

The exported game mounts the pak without parsing it — startup doesn't block on loading everything up front. The startup scene loads, and everything it references streams in on background threads, following the asset reference graph (scene → meshes → materials → textures). Completed loads register on the main thread under a per-frame budget, so even a burst of finished assets never causes a hitch. Additional scenes and zones stream the same way through the scene API.

Community

Mod Support

With mod support enabled, the shipped game scans a Mods/ folder next to the executable and mounts every .hpak it finds as an overlay, in alphabetical order. An entry with the same UUID as a base asset replaces it; new UUIDs add content; later mounts shadow earlier ones. Mods can even replace the startup scene. Mod paks are expected unencrypted — modders build them with the same pack tooling.

On disk

What Ships

FilePurpose
<Game>.exe / HorizonGame The game runtime (with the embedded pak key when encrypted).
Engine libraries Core/Scene/Rendering/Tools DLLs or dylibs, SDL3 — plus the C++ runtime on Windows.
<Project>.hpak + .hpak.manifest All assets; the manifest powers incremental re-exports.
project.hcfg Runtime config — window title, startup scene pointer, mod flag.
GameLogic.* (C++ projects) Your native gameplay library.
HorizonCodeGen.* (compiled HC) The compiled HorizonCode classes.
Python runtime (Python projects) Interpreter library, stdlib zip and native extensions.
Mods/ (optional) Overlay paks, scanned at startup.