-
Notifications
You must be signed in to change notification settings - Fork 12
Guides Unity Devcontainer Licensing
This guide explains how to configure Unity licensing for scripts/unity/run-unity-docker.sh in Codespaces and local dev containers.
The script supports three paths:
- Personal online activation (
UNITY_EMAIL+UNITY_PASSWORD) - Manual
.ulfactivation (UNITY_LICENSE) for serial-based licenses - Pro serial activation (
UNITY_SERIAL+UNITY_EMAIL+UNITY_PASSWORD)
It also persists Unity license cache artifacts between container runs using:
-
${UNITY_TEST_PROJECT_DIR}/.unity-license-cache/local-share-unity3d->/root/.local/share/unity3d -
${UNITY_TEST_PROJECT_DIR}/.unity-license-cache/config-unity3d->/root/.config/unity3d
By default, this is under /home/vscode/.unity-test-project/.unity-license-cache in the devcontainer.
You can override it with UNITY_LICENSE_CACHE_DIR if needed.
Use online activation. Unity Personal does not support manual activation via .alf / .ulf upload.
Set up secrets in GitHub first:
- Open the repository on GitHub.
- Go to
Settings->Secrets and variables. - Choose
Codespaces(for Codespaces-only secrets) orActions(for repository-level secrets reused by workflows). - Select
New repository secretand add each value below.
Reference: Managing encrypted secrets for your codespaces
Codespaces injects these secrets as environment variables inside the devcontainer.
run-unity-docker.sh reads them and forwards them into the Unity container via
Docker -e flags. Resulting license artifacts are persisted in the cache mounts.
Add these secrets:
UNITY_EMAILUNITY_PASSWORD
Use one of these methods:
- Export environment variables before running scripts.
- Use
scripts/unity/setup-license.ps1to generate.unity-secrets/credentials.env.
run-unity-docker.sh auto-loads .unity-secrets/credentials.env when environment variables are not already set.
Set all of these values:
UNITY_SERIALUNITY_EMAILUNITY_PASSWORD
For Pro, UNITY_SERIAL is required. If serial credentials are incomplete, the script fails early with a clear error.
For Personal online activation:
- Script attempts online activation with
UNITY_EMAILandUNITY_PASSWORD. - Script classifies failures as either hard licensing rejection or transient/network failure.
- For hard rejection (for example
Found 0 entitlement groups,com.unity.editor.headless was not found, invalid credentials), script fails fast. - If Unity reports
No license activation found for this computerorNo ULF license found, the script surfaces that as a machine-registration problem and stops. Unity Personal cannot recover through manual.alfupload. - If activation is still not successful, script exits with an actionable error.
For manual .ulf activation:
- This path is only for serial-based licenses.
- The
.ulffile must be generated for the same machine identity. -
UNITY_LICENSEcan be loaded from the environment or.unity-secrets/license.ulf.
For all activation methods, script verifies that at least one local license artifact exists before running Unity commands.
The script checks for at least one of these files:
/root/.local/share/unity3d/Unity/Unity_lic.ulf/root/.config/unity3d/Unity/Unity_lic.ulf/root/.local/share/unity3d/Unity/UnityEntitlementLicense.xml/root/.config/unity3d/Unity/UnityEntitlementLicense.xml
If none exists, the script fails early and points to this guide.
For personal online activation, the script also persists the raw activation log under:
/root/.config/unity3d/.activation-<timestamp>.log
Because /root/.config/unity3d is mounted from host cache, that log persists and can be attached to support tickets.
If the account does not have a compatible entitlement for the requested activation path, Unity logs often contain:
Found 0 entitlement groupsNo valid Unity Editor license found
Typical causes:
- Wrong Unity account for your organization/license.
- Personal account trying a Pro-only entitlement path.
- Expired or unavailable entitlement.
Actions:
- Verify the Unity account can activate the expected license type.
- If using Personal, do not switch to manual activation; Unity Hub is the only supported activation path.
- If using Pro, verify
UNITY_SERIAL,UNITY_EMAIL, andUNITY_PASSWORDtogether. - Re-run the script and confirm license artifacts are created in the mounted cache paths.
For editor automation in CI/devcontainers, this repo already runs Unity with:
-batchmode-nographics-quit
Those are the correct headless command-line flags for non-interactive workflows.
There is no required "headless toggle" in the Unity dashboard for this script path;
errors like Found 0 entitlement groups indicate a licensing-service decision for
the current account/machine activation, not missing CLI flags.
If you see these errors:
Found 0 entitlement groups and 0 free entitlements matching requested entitlement ids
Error: 'com.unity.editor.headless' was not found.
the issue is usually Unity licensing state for this account/machine combination, not missing command-line flags.
- Dedicated Server build target is for built player binaries.
- This repo is running
unity-editorin headless mode for compile/test automation. - So Dedicated Server target does not replace editor license activation requirements.
- Keep using
-batchmode -nographics -quit(already done in scripts). - Ensure credentials are correct (
UNITY_EMAIL,UNITY_PASSWORD). - If using a serial-based
.ulf, regenerate it for the same machine context (see next section). - If Unity still returns
Found 0 entitlement groupsorcom.unity.editor.headless, open a Unity support ticket and include full activation logs.
Headless flags control runtime/editor behavior, but license acceptance is still validated by Unity services. When services return no usable activation, local cache never gets populated and subsequent runs fail.
.ulf license files are encrypted with machine-specific hardware identifiers.
If you see this error:
Machine bindings don't match
Your .ulf file was generated on a different machine or with different hardware.
ULF files cannot be ported across:
- Different computers
- Different Docker containers (each container is a unique "machine")
- Different Codespaces instances
For local dev containers: Use online activation (UNITY_EMAIL + UNITY_PASSWORD) instead.
Once successful, the license artifact is cached and persists across container rebuilds.
For Codespaces: Store UNITY_EMAIL and UNITY_PASSWORD in GitHub Secrets.
Each Codespaces instance will regenerate the license on first run.
Generating new ULF files: If you absolutely need a .ulf file for a serial-based license:
- Generate an
.alfwithnpm run unity:generate-activation - Complete Unity's manual activation flow with your serial
- That
.ulfwill only work on this specific machine
Unity Personal cannot use this manual activation path.
The script can consume a .ulf file when one is provided. This should only succeed if:
- The
.ulfwas just generated moments ago in a previous Docker run on this machine - The Docker container still has the same hardware ID (unlikely after rebuild)
In practice, ULF fallback will almost always fail with "Machine bindings don't match" if:
- You're using
.ulffrom a different dev machine - You're trying
.ulfin a new Codespaces instance - You rebuilt the devcontainer (new container = new machine binding)
For Unity Personal, focus on online activation instead. Manual activation is not supported.
Online activation (email + password) is superior because:
- It generates a machine-specific license inside the container each time
- The license artifact is automatically cached between runs
- After first successful activation, subsequent runs don't re-authenticate
- Persists across Docker image rebuilds (cache is preserved)
- Works identically in Codespaces, CI/CD, and local dev containers
If Unity logs contain either of these messages:
No license activation found for this computer
No ULF license found
the current machine identity is not registered with your Unity account. This typically occurs on first run in a new Docker container or Codespaces instance when online activation cannot issue a license for the current machine.
Unity's current licensing docs state that manual activation does not work with Unity Personal.
In this repo, run-unity-docker.sh treats this as a stop condition and points you back to supported options:
- Activate through Unity Hub on a supported interactive machine.
- If you already have a machine-matched
.ulffrom a serial-based manual activation, place it at.unity-secrets/license.ulf. - If this is unexpected for a Personal account, attach the saved activation log to a Unity support request.
If you are using a paid license with a serial key, this repo still supports manual activation:
-
The
.alffile is automatically placed at.unity-secrets/manual-activation.alf. - Upload it at https://license.unity3d.com/manual (log in with your Unity account).
-
Enter your serial in Unity's manual activation flow, then download the
.ulffile and save it as.unity-secrets/license.ulf. -
Run:
npm run unity:retry-license
If for any reason the .alf was not auto-generated (for example, if the run was interrupted),
generate it explicitly:
npm run unity:generate-activationThis runs scripts/unity/generate-activation.sh, which requires UNITY_SERIAL, spins up a Docker container,
calls -createManualActivationFile, and copies the result to .unity-secrets/manual-activation.alf.
After placing .unity-secrets/license.ulf, run:
npm run unity:retry-licensescripts/unity/retry-license.sh:
- Validates that
.unity-secrets/license.ulfis present. - Clears stale cached license artifacts so Unity re-reads the new file.
- Re-runs
compile.shwith the new license loaded.
-
Check for licensing-state errors: If output contains
Found 0 entitlement groupsorcom.unity.editor.headless not found, capture full logs and treat it as a Unity licensing-service/account-machine issue. - Confirm secrets/env vars are present in the shell running the script.
- Confirm
.unity-secrets/credentials.envand.unity-secrets/license.ulfare present if using file-based loading. - Check script output for entitlement mismatch strings.
-
Verify credentials persist: After first successful activation, run
ls -la ~/.unity-test-project/.unity-license-cache/to confirm cache artifacts exist. -
For Docker image rebuilds: If you rebuild the devcontainer, the cache persists but
post-create.shfixes permissions automatically on next run. - Confirm
.unity-test-project/.unity-license-cache/directories are writable. - If output contains
No license activation found for this computerorNo ULF license found, treat it as a machine-registration problem. For Unity Personal, do not use manual activation; for serial-based licenses, follow the Machine Not Registered section.
Before running expensive Docker operations, validate your setup quickly:
npm run unity:validateThis script checks (without Docker):
- ✓ Credentials are available (env vars or
.unity-secrets/) - ✓ License files exist and are readable
- ✓ Cache directory is writable
- ✓ Docker daemon is running
- ✓ Required scripts are in place
It provides clear output showing what's missing and next steps.
Additional scripts for manual activation:
-
npm run unity:generate-activation— generates.unity-secrets/manual-activation.alffor serial-based manual activation workflows. -
npm run unity:retry-license— validates.unity-secrets/license.ulfis present, clears stale cached artifacts, and re-runs the compile command for serial-based manual activation.
If npm run unity:validate passes but compilation still fails, try:
bash scripts/unity/run-unity-docker.sh -batchmode -nographics -quit -projectPath /project -logFile -When you rebuild the devcontainer:
- The devcontainer is stopped and a new one is built from scratch
-
Your credentials (
UNITY_EMAIL,UNITY_PASSWORD) are preserved in.unity-secrets/credentials.env -
Your license cache is preserved in
/home/vscode/.unity-test-project/.unity-license-cache/(Docker persistent volume) - The
post-create.shscript runs automatically and fixes directory permissions - Next compilation run:
- Loads credentials from
.unity-secrets/credentials.env - Mounts the persistent cache into the new container
- Reuses the cached license artifact (no re-authentication needed)
- If cache is empty, performs fresh online activation on first run
- Loads credentials from
This means: After successful first-time activation, subsequent compilations reuse the cached license without re-authenticating, greatly reducing startup overhead. Network access is still used to validate the license is still active, but you won't experience multiple authentication prompts.
| Item | Persists? | Details |
|---|---|---|
.unity-secrets/credentials.env |
✓ Yes | Kept in workspace .gitignore, survives all rebuilds |
.unity-license-cache/ directory |
✓ Yes | Docker persistent volume, survives rebuilds |
| License artifact files (.ulf / .xml) | ✓ Yes | Stored in persistent cache volume |
/root/.local/share/unity3d inside container |
✗ No | Recreated from persistent volume on each Docker run |
| Docker image layers | ✗ No | Rebuilt each time, but cached locally |
Key takeaway: Credentials and cache both persist, enabling fast reuse
If you see Token not found in cache repeatedly:
- First activation likely failed silently (check for entitlement errors above)
- Run
ls -la ~/.unity-test-project/.unity-license-cache/to check if any artifacts exist - If cache is empty, verify credentials are correct and regenerate machine-matched activation data
- Delete cache and retry:
rm -rf ~/.unity-test-project/.unity-license-cache/ - Rerun compilation and check full output for error messages
📦 Unity Helpers | 📖 Documentation | 🐛 Issues | 📜 MIT License
- Inspector Button
- Inspector Conditional Display
- Inspector Grouping Attributes
- Inspector Inline Editor
- Inspector Overview
- Inspector Selection Attributes
- Inspector Settings
- Inspector Validation Attributes
- Utility Components
- Visual Components
- Data Structures
- Helper Utilities
- Math And Extensions
- Pooling Guide
- Random Generators
- Reflection Helpers
- Singletons