OZero Security
Documentation

Get Started

This guide walks you through installing OZero Security and setting up your first security protections. No prior security experience is needed — you will be up and running in about 3 minutes.

~3 minutes · Unity 2021.3 LTS+ · iOS 12.0+ / Android API 21+

Choose your goal

Start with the path that matches what you need to do now. Each card opens the relevant section of this manual or the API reference.

3-minute quick start Import the package, open the dashboard, apply a preset, and make the first build. Pre-release checklist Review build integrity, platform settings, diagnostics, and Release configuration. Feature configuration Configure the protection modules, common policies, and optional managed UI. Troubleshooting Resolve import, IL2CPP, stripping, platform, and license issues. License and Pro operations Understand activation, Native Variants, telemetry, portal policy, and subscription lifecycle. API reference Look up public types, fields, defaults, enums, callbacks, and error codes.

Overview

OZero Security protects Unity games by running security logic in the Native C++ layer, where most hacking tools cannot reach. The SDK provides ready-to-use modules that you enable through a simple dashboard inside the Unity Editor. No manual scene setup or boilerplate code is required to get the core protection running.

What you get out of the box:
  • Build integrity check (app tampering detection)
  • Speed hack and time hack detection
  • Memory injection monitoring
  • Encrypted in-game variable types (Secure Types)
  • Encrypted save files and PlayerPrefs
Zero-wiring Auto-bootstrap & Encrypted Config
  • Enabled detectors are prepared automatically when the SDK starts — no scene setup and no boilerplate calls required.
  • Security settings are protected during the build so plaintext configuration is not exposed in normal player deployments.
  • A Native C++ runtime guard adds an additional validation layer beyond managed Unity code.
  • Threat response is centralized through SDK policy and Pro telemetry, making field investigation easier without exposing implementation details.

1 Import the Package

Open the Unity Editor and import the OZero Security package. You can import it via the Unity Package Manager or by double-clicking the .unitypackage file.

In the Import Unity Package dialog that appears, leave all items checked and click Import. All required scripts, native plugins, and editor tools will be added to your project automatically.

Import Unity Package dialog with all OZeroSecurity files selected
After importing, Unity may need a moment to compile scripts. Wait until the progress bar in the bottom-right disappears before continuing.

2 Open the Dashboard

Once the import is complete, open Config Dashboard from the Unity menu bar:

Window -> OZero Security -> Config & Dashboard
OZero Security Config Dashboard opened in the Unity Editor

A custom Editor window will open. This is the central control panel for all OZero security modules. You do not need to touch anything in the Project hierarchy — everything is managed here.

Unity Editor Menu Reference

OZeroSecurity uses Window > OZero Security for setup windows and Tools > OZero Security for diagnostic or bake commands. Security presets are intentionally applied from Config & Dashboard, so you can review the resulting settings before saving.

Menu Role When to use
Window > OZero Security > Config & DashboardOpens or creates the main OZeroSecurityConfig asset.Use this first to apply presets, enable modules, configure response policy, and review build-integrity settings.
Window > OZero Security > License SettingsOpens or creates OZeroLicenseConfig.Use this to enter Standard, Plus, or Pro license settings, server endpoints, and telemetry options.
Window > OZero Security > Check SetupRuns editor diagnostics for common project and release-configuration issues.Run after import, before a release build, or when a module does not behave as expected.
Tools > OZero Security > Check Integrity ManifestOpens an OZero integrity manifest and displays the decoded content for inspection.Use during build-integrity troubleshooting or support investigation.
Tools > OZero Security > Bake Security Config BlobRegenerates the protected security config blob in StreamingAssets.Use for advanced debugging or CI workflows. Normal player builds bake this automatically.
Tools > OZero Security > Bake Assembly HashRe-bakes oz_ahash.bin for the most recent build output.Use only after a code-only rebuild when the full build pipeline was not re-run.
Tools > OZero Security > Keystore SHA ExtractorExtracts SHA-1 and SHA-256 fingerprints from an Android keystore.Use when filling Android signing fingerprints for Build Integrity checks.
Tools > OZero Security > Add Debug SHA Key to ConfigFinds the Android debug keystore and adds its SHA-256 fingerprint to the config.Use only for local Android debug builds. Release builds should use the release signing key fingerprint.
Tools > OZero Security > Steam Anti-Piracy > Scan Steam RedistributableScans a PC build or plugin folder for Steam redistributable files and known emulator artifacts.Use before Steam release packaging or when checking whether suspicious Steam files are included.
Tools > OZero Security > Check Time.timeScale UsageScans scripts for direct Time.timeScale writes that can conflict with OZero time protection.Run before release or when the Speed & Time Hack module reports a project-side time-scale policy issue.

3 Enable Modules

Inside the Dashboard, you will see a list of available security modules with toggle switches. Enable the modules you want to use. The recommended starting set is shown below.

OZero Security Config Dashboard in the Unity Editor

Security Presets

Choose a preset first, then adjust individual modules only when your project needs a custom policy. For most live games, start with Standard because it balances protection, performance, and false-positive risk.

Preset Recommended use Policy summary
Low Prototype, development builds, or early QA Keeps only lightweight checks active. Platform-native checks and force quit are relaxed so test environments do not get blocked too early.
Standard Recommended default for most released games Enables the core protection set, startup validation, runtime re-validation, emulator checks, and recommended IL2CPP file coverage while keeping compatibility practical.
Strict High-risk live service, PvP, or competitive builds Turns on maximum coverage and treats more failures as fatal. Use after testing your platform, signing, and store distribution flow.
Module What it does Recommended
Build Integrity Validator Detects if the app binary was modified Yes
Speed Hack Detector Catches time-manipulation cheats Yes
Injection Detector Monitors for memory hooking tools Yes
Install Source Validator Blocks pirated APKs (Android only) Optional

Turn on the modules you want to use in the dashboard and save the OZeroSecurityConfig asset. When the player starts, the SDK automatically prepares the enabled modules.

You do not need to place a separate object in the scene. Turn on the modules you need, save the settings, and those modules will initialize automatically from the next run.

License Model — Standard / Plus / Pro

OZero Security ships in three tiers. Standard is fully serverless with the shared native module. Plus stays serverless but adds app-specific Native Variant packages bound by manifest and Bundle ID. Pro includes Plus and unlocks server-side capabilities such as Cloud Telemetry, Signed Time, remote policy, attestation, and per-device limits.

The matrix below is the developer-facing summary of what the SDK actually does at runtime per tier. For the full feature comparison, see the License Modes comparison on the homepage.
Aspect Standard Plus Pro
License key — (none) OZ-PLS-XXXX ×6 OZ-PRO-XXXX ×6
Network at boot Never — fully offline No runtime server required; portal download only One POST /v1/activate per device, then cached
9 detector modules All 9 — Build / Speed / Inject / Device / Source / Physics / Memory / File / PlayerPrefs All 9 (identical local modules) All 9 (identical to Standard)
Native Variant Shared native module App-specific Variant + manifest binding Included
Cloud Telemetry Off (silent no-op) Off (serverless) On — abort events posted to /v1/telemetry
Signed Time (anti-clock-tamper) Off — WebTime uses HTTPS HEAD only Off — same as Standard On — digitally-signed /v1/time
Per-device cap Unlimited (no key, no enforcement) Project-bound license; no runtime device cap Default 5 / adjustable
Source code access Managed C# only Managed C# only Managed C# only
If you ship Standard today and later upgrade to Plus or Pro, keep the same gameplay code. Plus adds a Variant manifest/native package, while Pro additionally enables server capabilities through OZeroLicenseConfig.

Registering a Plus / Pro License Key

Standard works without any separate license setup. For Plus or Pro, create the OZeroLicenseConfig asset in Unity and enter the license key issued to your project. Plus uses this key to download the project-specific Native Variant package from the portal and to confirm during build that the package belongs to the current project. Pro also uses the key for runtime activation and Pro-only server features.

1. Create the config asset

Open Window → OZero Security → Config & Dashboard. In the License & Server section, click Create OZeroLicenseConfig. The button creates the asset in the correct Resources/ folder, so you do not need to create folders or move the asset manually.

You cannot create this asset directly from the Project window's Create Asset menu. OZeroSecurityConfig and OZeroLicenseConfig do not expose CreateAssetMenu entries to prevent assets from being created in the wrong location. Use the Dashboard button instead.

2. Fill in the Inspector fields

Field Required for Description
tier All Choose the license tier for this build. Standard uses the shared native module. Plus adds a project-specific Native Variant and manifest validation. Pro adds runtime activation, telemetry, and remote policy features on top of Plus.
licenseKey Plus / Pro The license key issued to your project. Plus keys use the OZ-PLS-... format, and Pro keys use OZ-PRO-.... Plus uses this key to confirm that the Native Variant package belongs to the current project. Pro also uses the same key for server activation and Pro server features.
appIdentifier Auto When Pro activation runs, the SDK sends Unity's Application.identifier value with the request. If this value does not match the Bundle ID or Package Name registered in the customer portal, activation can be rejected. Check the Identifier in Unity Player Settings first.
serverBaseUrl Pro runtime The base address used by Pro features when they communicate with the OZero server. It is used for activation, telemetry, signed time, attestation, and server policy checks. Standard and Plus do not call this URL at runtime. Keep the default https://api.ozerosecurity.com unless OZero support gives you a dedicated endpoint.
serverPublicKeyHex Pro runtime The server signing public key shown in Customer Portal > Server Key. Pro runtime uses this value to confirm that activation, signed time, attestation, and offline policy responses came from the OZero server. Plus does not use this field. Plus/Pro Variant manifests are verified separately with the SDK-embedded OZero Variant signing key.
previousServerPublicKeyHex Pro optional The previous public key used only during a short Pro server signing-key rotation window. Fill this only when OZero support asks you to rotate keys; otherwise leave it empty. Plus does not use this value.
tokenTtlSeconds Pro runtime How long a successful Pro activation result can be used while the player is offline. The default 604800 is 7 days. After that time, local protection still runs, but Pro server features such as telemetry and signed time stay off until activation succeeds again.
offlineProPolicyMode Pro A Pro option that decides whether a build or version blocked in the portal should still be blocked while the device is offline. Most live games should use the recommended ApplyCachedBlockPolicies mode. Consider RequireFreshPolicy only for online-only games that must stop when a fresh policy is unavailable. IgnoreCachedBlockPolicies is for compatibility checks or special tests and is not recommended for live builds. See OZeroOfflineProPolicyMode for each value.
activationTimeoutSeconds Pro runtime How many seconds the SDK waits for the Pro activation request, /v1/activate. The default is 6.0. If the server does not answer in time, the SDK does not block scene loading. It uses a valid Pro cache when available; without a cache, only the selected server features stay unavailable while local protection continues.
enableLog Optional When enabled, license-flow events such as cache use, activation success, timeout, and signature mismatch are written through OZeroSecLog. Keep it on during integration because it makes setup issues easier to find. Turn it off for release builds if you want fewer logs.
Pro server features
enableDevicePolicyHeartbeat Pro Periodically asks the Pro server whether the current device has been blocked in the customer portal. If the server returns DEVICE_BLOCKED, the SDK clears cached Pro entitlement data and blocks the app.
devicePolicyHeartbeatInterval Pro The base interval for checking whether the device is blocked. Default is 300 seconds. Set it to 0 to disable periodic checks.
devicePolicyHeartbeatJitterPercent Pro A percentage that slightly spreads out the check timing so many devices do not call the server at the same moment. The default 20 means the SDK shifts the timing a little around the configured interval. Valid range: 0 to 75.
enableSecurityLevelCheck Pro When enabled, the app asks /v1/security-level to confirm this build's security settings at startup. The server can reject the build if it is below the minimum level required in the portal. Default is false.
declaredSecurityLevel Pro The security level this build reports to the server. Default is Standard. Use Low for prototypes or internal tests. Use Strict only after QA has confirmed the stronger policy does not block normal users.
failOnSecurityLevelReject Pro When enabled, the app follows the block flow if the server clearly rejects the security level or config hash. Simple network errors, server maintenance, or license maintenance states are not treated as tampering; they only disable Pro server features.
securityLevelCheckInterval Pro How often the app checks the security level again while it is running. Default 0 means the check runs only once at startup.
securityLevelCheckJitterPercent Pro A percentage that slightly spreads out repeated security-level checks so many devices do not call the server at the same moment. Default is 20. Valid range: 0 to 75.

3. Build & verify

You do not need to add extra code. When the app starts, the SDK automatically reads the OZeroLicenseConfig asset. On the first run, check the Player log for a line such as [OZeroLicense] activated; tier=pro caps=5. If you configured Pro but the log says Standard mode, check the asset location and name first. The asset must be under a Resources/ folder and must be named exactly OZeroLicenseConfig.

The license key cannot be hidden at runtime like a password because it is included with the build. Still, do not post it in public repositories, documentation, or screenshots. If exposed, someone else can consume your device allowance. Treat it like a product code.

Server Activation Flow

Pro licenses are checked automatically when the app starts. This process is designed not to block the game startup flow. If the server is slow or the network is temporarily unavailable, the SDK checks stored activation info first and continues with it when it is still usable.

Boot sequence

  1. The SDK automatically initializes the license runtime when the app starts.
  2. Standard and Plus do not need runtime server activation, so local protection starts immediately.
  3. When optional Pro server features are configured, Pro sends a /v1/activate request in the background to check the current license and device state.
  4. If activation succeeds, Pro server features such as telemetry, signed server time, and build attestation become available.
  5. If server maintenance, a temporary network error, or a timeout occurs, the SDK uses stored activation info when possible. If no usable stored info exists, or if the license is expired, suspended, or revoked, only the selected Pro server features become unavailable or degraded. Acquired Native Variants and local protection continue unchanged.

Transmitted data

The activation request is a small JSON POST. The basic request includes licenseKey, deviceId, sdkVersion, and platform. When Unity can provide values, appIdentifier, companyName, productName, and webglOrigin are also sent. By default, deviceId uses Unity's device identifier, but you can replace it with an account id or your own UUID source through OZeroLicenseRuntime.DeviceIdProvider.

POST https://api.ozerosecurity.com/v1/activate
Content-Type: application/json

{
  "licenseKey":    "OZ-PRO-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX",
  "deviceId":      "<DeviceIdProvider result; default SystemInfo.deviceUniqueIdentifier>",
  "sdkVersion":    "<OZeroSdkVersion.ManagedVersion>",
  "platform":      "<android | ios | windows | macos | linux | webgl | ...>",
  "appIdentifier": "<Application.identifier>",
  "companyName":   "<Application.companyName>",
  "productName":   "<Application.productName>",
  "webglOrigin":   "<WebGL origin only>"
}

The server returns a signed token, the resolved tier, available capabilities, whether server features are enabled, the token expiry time, and the server-unreachable posture. The SDK verifies the signed token with the configured public key before accepting Pro capabilities.

Graceful degradation

Server maintenance, network timeouts, license expiry, suspension, revocation, and bundle mismatch are not treated as tamper. In those cases, only the selected Pro server features become unavailable or degraded; acquired Native Variants and local protection continue unchanged. Confirmed tamper states such as build mismatch, blocked build, injection, and debugger detection follow the configured threat-response policy.

If you want to know whether the live activation succeeded (rather than just trusting cache), await OZeroLicenseRuntime.Initialize(); from your own bootstrap and inspect OZeroLicenseRuntime.Entitlement?.cachedAtMillis. A value within the last few seconds means the server answered fresh; an older value means you are running on cache.

Offline Behaviour

The short version: losing the network does not stop the game or local protection. Standard does not use the server at all. Pro keeps the same offline local protection, while explicitly selected server features can use saved activation information for a limited time.

Standard — starts without internet

Standard does not ask any server for permission. It runs the local protection modules bundled in the app, so the game starts even when the player is offline. Only Pro server features such as telemetry and signed time are unavailable.

Pro — local protection stays offline; selected server features use cache

When optional Pro server features are enabled, the device and license are confirmed through /v1/activate while online. The SDK encrypts the result and saves it in PlayerPrefs so those selected server features can tolerate a temporary disconnection. This activation does not gate builds made with an acquired Native Variant or local protection.

tokenTtlSeconds is the lifetime of that saved server-feature result. The default is 604800 seconds, or 7 days. After it expires offline, only server-dependent features such as telemetry upload and signed-time verification stay unavailable until the next successful activation. The game, acquired Native Variant, and local detectors continue unchanged; the SDK does not silently switch the product tier to Standard.

Pro — portal-blocked builds stay blocked offline

A temporary server or network problem is different from a build that an operator intentionally blocked in the portal. When Pro activation succeeds, the server also sends a signed block list, such as blocked build hashes, SDK versions, and app versions. The SDK stores this block list separately from the activation result.

With the recommended ApplyCachedBlockPolicies mode, a blocked build is still rejected by Build Integrity while the saved block list is valid, even if the player starts the game in airplane mode. After you change block rules in the portal, each device needs one successful online activation to receive the new rules.

If a device has never completed Pro activation before, it cannot receive the portal block list during a fully offline first launch. For live games, keep server-side session checks or OZA validation as the final gate for purchases, rewards, currency grants, and other high-value actions.
State Detectors Telemetry Signed Time
Online, fresh activation All 10 On On On
Offline, saved Pro info still valid All 10 On Off (offline events are not stored) Uses WebTime fallback when possible
Offline, saved Pro info expired All 10 On Off (until next online activation) Off (until next online activation)
First launch + fully offline All 10 On Off until first online launch Off until first online launch
Telemetry is sent only while the device is online. If an event happens offline, the SDK records one warning log and discards that event instead of saving it to disk. This avoids leaving a local queue that attackers could edit. When the device is online again, new detection events are sent normally.

Troubleshooting

If something looks wrong, first search the Unity Player log for [OZeroLicense]. This tells you whether the SDK started as Standard, whether Pro activation succeeded, and why it downgraded to Standard when activation failed. For security-event upload issues, also search for [OZeroTelemetry].

What you see in the log Meaning What to do
[OZeroLicense] Standard / serverless mode. The SDK started in Standard mode. This is normal if you meant to use Standard. If you expected Pro, confirm that OZeroLicenseConfig.asset was created from Window → OZero Security → Config & Dashboard and is under Resources/. The asset name must be exactly OZeroLicenseConfig, and tier=Pro plus licenseKey must be filled.
Pro->Standard downgrade: /v1/activate returned LICENSE_NOT_FOUND The server could not find this license key, or the key is not usable right now. Compare licenseKey with the key shown in the Customer Portal. Keep casing and dashes exactly as shown. If the portal status is pending, suspended, revoked, or expired, Pro activation will not succeed.
ANDROID_BUNDLE_ID_MISMATCH / WINDOWS_PRODUCT_NAME_MISMATCH The app identity in this build does not match the value registered in the portal. For Android/iOS, check Application.identifier in Player Settings. For Windows, check Company/Product names. For WebGL, check the runtime origin. If these do not match the portal record, /v1/activate is rejected. After changing the value, test with a fresh build.
activation token signature verification failed The server responded, but the SDK decided it could not trust that response. This applies to Pro activation only. Copy the Active publicKey from Customer Portal > Server Key into OZeroLicenseConfig.serverPublicKeyHex. Paste only the 64-character hex value, not the kid prefix. If it still fails with the exact value, test once on a direct network outside corporate proxy/MITM equipment.
private native variant manifest signature is invalid The Variant package manifest is missing, edited, or was not signed by the trusted OZero Variant signing key. Do not fix this by filling serverPublicKeyHex. For Plus and Pro Variant packages, re-download the assigned Variant package and keep the manifest and native plugin files from the same package. If the newly downloaded package still fails, send the manifest file and build log to OZero support.
DEVICE_BLOCKED This device is blocked in the Customer Portal. Review the security events for that deviceId in the portal. Keep the block if it was a real attack or policy violation. If it was a QA device or a false positive, unblock it in the portal. The SDK clears stored Pro entitlement and runs the block flow when it receives this response.
ACTIVATION_LIMIT This license has no room for another newly activated device. Remove old test devices in the portal. If this is caused by real users, raise the device limit for the license.
/v1/activate timed out / network error The device could not reach the server, or the response was too slow. Check whether the device can reach https://api.ozerosecurity.com/health. Also check firewall, proxy, DNS, and captive-network conditions. In high-latency regions, try increasing activationTimeoutSeconds. If saved Pro info exists, the SDK uses it first.
cached entitlement past TTL; clearing. The saved Pro information is past its trust window. If the device stays offline longer than tokenTtlSeconds, saved Pro info is no longer trusted. The game keeps running at Standard level, and Pro features return after the next successful online activation. If long offline play is common, increase TTL.
SERVER_NOT_CONFIGURED / SIGN_FAILED The server could not sign the activation token. This is usually a server Server Key or encryption-key state issue, not a client-side typo. Check the Customer Portal Server Key status. On production, send the log time, partial licenseKey, and platform to OZero support.
We recommend turning off enableLog in release builds. Logs are useful for QA, but general user builds do not need to expose tier, feature state, or detection-flow details.

Project Settings

Before configuring individual security modules, check the Unity Player Settings that affect native plugins, store builds, and platform validation.

Minimum Build Targets

Platform Minimum target Notes
iOS 12.0+ For iOS builds, set Project Settings > Player > iOS > Target minimum iOS Version to 12.0 or later. OZero does not overwrite this PlayerSettings value; keep it aligned with your app support policy.
Android API 21+ For Android builds, set Project Settings > Player > Android > Minimum API Level to Android 5.0 'Lollipop' (API level 21) or later. Use IL2CPP and ARM64 for store release builds.
Apple privacy manifest: The SDK includes PrivacyInfo.xcprivacy. The Unity post-processor adds it to the iOS Xcode app target and to Contents/Resources for macOS. The manifest declares the UserDefaults CA92.1 reason because OZero uses Unity PlayerPrefs for app-local SDK state. Keep the manifest in the final app and review the Xcode privacy report before submission.

Recommended security and size settings for release builds

When you publish the final release build, OZero recommends the following Unity settings to strengthen the build and reduce app size.

Security hardening (IL2CPP): On Android, iOS, and other Unity-supported targets, set the scripting backend to IL2CPP. IL2CPP does not make reverse engineering impossible, but it reduces direct C# metadata exposure and helps OZero security checks run on a stronger release baseline. Path: Project Settings > Player > Other Settings > Scripting Backend

Size optimization (Managed Stripping): Managed Stripping removes unused managed code to reduce app size. If too much code is stripped at once, the app may fail at runtime, so start with Low or Medium.

Important: After changing these settings, test scene transitions, save/load behavior, Addressables, and external SDKs such as payments or ads on a real device before increasing the stripping level.

For Windows Standalone builds, install Microsoft Visual C++ Redistributable 2015-2022 (x64) on the target PC. If this runtime is missing, Windows may fail to load the OZero native plugin and the app can close at startup. When distributing through Steam, a launcher, or your own installer, include the redistributable as a prerequisite.

Android ProGuard / R8 Settings

OZero Security does not require a separate Java SDK package, but Android release builds that enable Minify, ProGuard, or R8 must preserve Unity's Java bridge and any custom Android bridge classes used by your project. This keeps JNI calls for package information, installer source, APK signing certificate checks, and boot asset loading stable after obfuscation.

In Unity, open Project Settings > Player > Android > Publishing Settings. If Minify Release is enabled, also enable a custom ProGuard file and add the rules below to proguard-user.txt. If Minify is disabled, no extra ProGuard setup is required.
# OZero Security - Unity Android ProGuard/R8 keep rules
-keep class com.unity3d.player.UnityPlayer { *; }
-keep class com.unity3d.player.UnityPlayerActivity { *; }
-keep class com.unity3d.player.UnityPlayerGameActivity { *; }
-keep class com.unity3d.player.UnityPlayerForActivityOrService { *; }
-keepattributes *Annotation*,InnerClasses,EnclosingMethod,Signature

# If your game adds custom Java/Kotlin bridge classes that OZero or your code
# calls through AndroidJavaClass / AndroidJavaObject, keep those classes too.
# Replace the package below with your own bridge package.
# -keep class com.yourcompany.yourgame.bridge.** { *; }

5 Configure OZeroSecurityConfig

The OZeroSecurityConfig ScriptableObject asset is included when you import the package. Select it in the Project window to inspect and adjust all security module settings. The config is a singleton — access it at runtime via OZeroSecurityConfig.Instance.

OZeroSecurityConfig Inspector panel in the Unity Editor

General Settings

These top-level fields apply globally across all modules.

Field Type Default Description
developerSecret string "" Project-specific secret used to protect OZeroSV_File and OZeroSafePlayerPrefs data. Generate it with Generate Secure Secret in the Config Dashboard, keep it out of public logs and repositories, and do not change it after release. If this value changes after release, protected save files and Safe PlayerPrefs written by older builds cannot be decrypted by newer builds.
enableLog bool false Enables internal debug logging from OZero Security. Disable in production builds to avoid leaking detection logic details.
enableFailureDiagnostics bool false Writes local security failure diagnostic files to Application.persistentDataPath. Enable only for QA or customer support sessions because files can include module names, hashes, device state, installer package names, and runtime configuration.
Important: before your first release, click Generate Secure Secret and save the generated developerSecret. Do not change it after launch. If this value changes, existing OZeroSV_File and OZeroSafePlayerPrefs data cannot be decrypted by newer builds.

Managed Verification UI Management

Pro only. Configure the online revalidation, network retry, and block/exit dialogs used by Build Integrity and Steam DRM. Install Unity UI and TextMeshPro from Package Manager before importing the optional OZero TMP dialog package. On Unity 6, TextMeshPro is included in Unity UI 2.x. Projects that do not use TextMeshPro should use Custom UI / Callback Only.

Build preflight: when BuiltInBlockingDialog or BuiltInNonBlockingDialog is selected, every player build requires TextMeshPro, TMP Essential Resources, and the imported OZeroSecurity_BuiltInDialog_TMP.unitypackage. If any prerequisite is missing, preflight stops the build. Open Window > OZero Security > Check Setup, find the Built-In TMP dialog error, click Import Package, and wait for Unity script compilation to finish before rebuilding. Choose Custom UI / Callback Only instead when your game provides its own UI.
Guide: to extend built-in UI languages, use Tools > OZero Security > Localization > Managed Verification Text. Enter the Language Code (ISO 639-1) and translation text for each item, then click Generate / Save to create the JSON resource automatically. The built-in UI is then displayed according to the player's Application.systemLanguage.
Font scope: the optional package embeds Static TMP SDF subsets only for OZero's supplied EN, KO, JA, ZH-CN, and ZH-TW dialog strings. The supplied strings need no extra font work. If you change text, add a locale, or display characters outside that set, regenerate the Static SDF from the charset files or use fonts referenced by a project-owned custom prefab. Otherwise missing glyphs may appear. Keep customized prefabs and fonts in a project-owned folder instead of editing the OZero originals.
Field Type Default Description
managedVerificationUiPolicy (Pro)enumBuiltInBlockingDialogPro only. Chooses the user-facing flow for OZero Managed Build Integrity and Steam DRM states. Built-in blocking/non-blocking dialogs require TextMeshPro and the optional OZeroSecurity_BuiltInDialog_TMP.unitypackage. Use Custom UI / Callback Only when your game replaces that UI through RegisterUserManagedVerificationStateCallback or when the project does not import the TMP dialog package.
managedVerificationDialogPrefabResourcePath (Pro)string""Optional Resources path for a copied/customized OZero Managed Verification UI prefab. Leave empty to use the default prefab from the optional TMP dialog package; import OZeroSecurity_BuiltInDialog_TMP.unitypackage first, then create a project-owned copy before changing the visual design.
managedVerificationRetryTimeoutSeconds (Pro)int15Maximum time to wait after the user presses Retry before moving to a retry-timeout state. Use this to avoid leaving the player in an indefinite verification wait.
managedVerificationOnlineRequiredTimeoutSeconds (Pro)int120Maximum time to keep the online-required dialog waiting before the configured timeout action is applied.
managedVerificationTimeoutAction (Pro)enumBlockSessionControls what happens when verification does not recover in time: keep showing the dialog, block the protected session, abort the app, or only invoke callbacks for a custom flow.
autoRetryManagedVerificationWhenNetworkRestored (Pro)boolfalseAutomatically retries managed verification after network connectivity returns. Enable only when your game can safely retry without an explicit player action.
managedVerificationLanguageCode (Pro)stringautoLanguage code for the built-in verification UI. Use auto to follow Application.systemLanguage, or specify a code such as ko, en, ja, zh-CN, zh-TW, or a custom JSON file code.
managedVerificationFallbackLanguageCode (Pro)stringenFallback language used when the requested language JSON is missing. Custom files use Assets/OZeroSDK/Resources/OZeroLocalization/ozero_ui_text_{code}.json.

Global Threat Response

Controls what happens when any security module fires a detection event.

Field Type Default Description
forceQuitOnDetection bool true Automatically force-quits the application when a confirmed threat is detected. In Standard and Strict presets this is enabled so the internal fallback receiver can enforce the response even if a managed callback is patched or missing. Disable only for controlled QA flows where you intentionally want to observe detections without terminating the app.
fatalCallbackGraceSeconds float 10 Maximum seconds allowed for your security callback UI to notify the player before the SDK exits automatically. Set to 0 only when you intentionally want the old immediate-exit behavior.

Integration Troubleshooting

If the app closes after enabling OZero Security, or only fails in a specific environment, first use the local diagnostic file to identify which module reacted. Instead of guessing, follow the tables below using the module, subCode, and reason values from the file.

Turn on Enable Failure Diagnostics only while investigating a QA or customer-support issue. The file can include module names, hashes, device state, installer package names, and runtime settings. Do not ship public release builds with this option left on.

When the app keeps closing

Step What to do How to read it
1Open Window > OZero Security > Config Dashboard in Unity, then turn on Key Common Settings > Enable Failure Diagnostics in OZeroSecurityConfig.Use this only while investigating a QA or support issue, and do not ship public release builds with it enabled.
2Before changing more settings, reproduce the issue once with the same build.If you change several settings before reproducing, it becomes harder to identify the cause. Capture the diagnostic file for the current state first.
3Open the latest ozero_*_failure.log file under Application.persistentDataPath.Build Integrity may also create ozero_integrity_failure.log plus a more specific file such as ozero_integrity_platform_native_failure.log. If the app exits very early and no failure log exists, also check ozero_abort.txt and the Player log.
4After collecting the file, turn Enable Failure Diagnostics off again.Do not keep local diagnostic files enabled in public release builds unless your support process explicitly requires it.

Fields you will usually see

Field Meaning What to check next
moduleThe protection area that produced the event.Start with the matching FAQ row, then open the related manual section such as Build Integrity, Speed & Time Hack, Injection, Install Source, or License.
subCode / checkNameA shorter reason code or check name.Use it to choose the matching symptom family below. For example, platform_native means you should first check platform, emulator, signing, root, or jailbreak settings.
reason / subReasonA human-readable summary of why the SDK reacted.Treat this as a hint, not the final answer. Check module and subCode first, then find the row below that uses the same keyword.
platform / buildTypeWhere the app was running and whether it was an editor, development, or release build.Separate QA-only emulator or development-build issues from real release-device issues.

Common symptoms and first checks

Symptom Likely area First thing to try
The app closes right after applying OZero.A security response fired during startup.Enable Failure Diagnostics, reproduce once, then read module, subCode, and reason. If there is no failure log, check ozero_abort.txt and the Player log. Also run Window > OZero Security > Check Setup in Unity.
The app keeps closing on an Android emulator.Build Integrity / platform native checks may be treating the emulator as an unsupported runtime.For emulator QA, relax blockEmulator (Android) or the related platform check policy. Re-enable the release policy before store builds if your game should block emulator environments.
License activation fails or an optional Pro server feature is unavailable.License key, app identity, network, or server signing key.Open License Troubleshooting and check the exact log line, such as LICENSE_NOT_FOUND, ANDROID_BUNDLE_ID_MISMATCH, timeout, or signature verification failure.
Build Integrity or manifest validation fails.Missing, old, unsigned, or mismatched manifest data.Run Check Setup, regenerate the integrity manifest, validate signing keys, and make a clean build. Do this after code, IL2CPP output, watched files, or the manifest signing key changes.
The app closes after pause, slow motion, or fast-forward.Direct Time.timeScale writes can look like time manipulation.Use OZeroTime.timeScale. Keep TimeScaleTamperExemptions only for verified plugins or legacy adapter scripts.
The app closes during a long loading screen.The native Watchdog may not receive heartbeat updates while the main thread is blocked.Wrap trusted long loading boundaries with OZeroWatchdog.BeginLoadingGrace. Do not use it to hide normal gameplay stalls.
Android works before Minify/ProGuard/R8, but closes after enabling it.Unity or custom Android bridge classes may have been stripped or renamed.Apply the Android ProGuard / R8 keep rules, especially for Unity bridge classes and any custom Java/Kotlin bridge your project calls.
Windows Standalone closes immediately on a clean PC.The OZero native plugin or VC++ runtime may not load.Install Microsoft Visual C++ Redistributable 2015-2022 (x64) and confirm the OZero native plugin is included in the build output.
A normal overlay or recording tool triggers an Injection event.Injection/Hooking is observing a loaded module.First check the detected module path, hash, and signer fingerprint from Failure Diagnostics or Pro telemetry. Register an exception only after QA confirms the module is trusted. Add local exceptions in the Injection settings injectionWhitelistEntries; Pro customers can update the same policy during live operations through the customer portal server-managed whitelist.
The build stops because the optional Built-In TMP Dialog package is not ready.A built-in Managed Verification UI policy is selected, but TextMeshPro, TMP Essential Resources, the OZero dialog component, or its default prefab is missing.Open Window > OZero Security > Check Setup and click Import Package on the Built-In TMP dialog error. Wait for package import and script compilation, run Check Setup again, then rebuild. If the game supplies its own UI, select Custom UI / Callback Only.
Release reminder: Before shipping, review any settings you relaxed during troubleshooting. Emulator blocking, force-quit policy, manifest signing, ProGuard rules, and local diagnostics should be restored or intentionally confirmed for the release policy.

Build Integrity Settings

Configures the build integrity validator that detects modified game files, debugger attachment, and suspicious runtime environments.

Field Type Default Description
Activate Build Integrity checkbox On The Dashboard activation checkbox. Internally this maps to useIntegrity, but users should enable or disable the module with the Activate checkbox.
validateOnStartupbooltrueRuns the integrity check immediately when the game launches.
validateInEditorboolfalseAlso validates in the Unity Editor for testing. Keep this off during ordinary development unless you are intentionally testing integrity behavior.
enablePeriodicValidationbooltrueRepeats integrity checks while the game is running. Disable only when startup-only validation is enough for your build.
periodicCheckIntervalfloat300 sBase interval in seconds for periodic validation. Set to 0 or less to disable periodic checks.
periodicCheckJitterPercentfloat35%Adds random variation to the validation interval so check timing is harder to predict. Exact intervals and ranges are not documented publicly; the default values are recommended.
timingAnomalyConsecutiveRequiredint7How many timing-only anomalies must accumulate before debugger timing drift is treated as a violation. Strong debugger signals can still fail immediately.
timingAnomalyWindowSecondsfloat900 sTime window used to accumulate timing-only anomalies. A longer window is more tolerant; Strict uses a shorter window.
timingAnomalyFrameHitchSuppressionSecondsfloat20 sTemporarily suppresses timing-only debugger checks after a large frame hitch, such as scene loading, shader compilation, GC, or OS scheduling stalls.
checkAssemblyHashbooltrueVerifies managed assembly hashes against the manifest generated at build time.
checkDebuggerbooltrueDetects debugger attachment and debugger-like runtime timing behavior using native platform checks.
failOnDebugBuildboolfalseTreats a Unity Debug build as a violation. Enable this for release-only validation flows after QA is complete.
checkPlatformNativebooltrueRuns native platform checks such as emulator, debugger, virtualization, signing, proxy, or tool-process signals depending on platform.
failIfManifestMissingboolfalse*Inspector default is off so development builds can iterate before a manifest exists. In non-development player builds this is forced on, so a missing or unreadable oz_manifest.ozero is treated as a violation.
failIfAssemblyHashBlobMissingboolfalse*Inspector default is off for development convenience. In non-development player builds this is forced on, so deleting the generated assembly hash blob cannot silently bypass hash verification.
requireCodeSignature (Windows)boolfalseRequires the Windows main executable to be code-signed.
blockVirtualMachine (Windows)boolfalseBlocks common VM environments such as VirtualBox, VMware, or QEMU. Hyper-V has a separate switch.
blockHyperV (Windows)boolfalseBlocks Hyper-V VMBus signals. Use carefully because it can also block WSL2, Docker Desktop, and Windows Sandbox users.
blockNetworkProxies (Windows)boolfalseDetects execution signals that look like network proxy, packet inspection, or traffic analysis tools. Use it for competitive builds, but test possible false positives first.
blockReverseEngineeringTools (Windows)boolfalseDetects execution signals that look like reverse-engineering or debugging tools. Validate separately for development/QA and live environments.
blockSystemMonitorTools (Windows)boolfalseDetects execution signals that look like process or system monitoring tools. Consider possible false positives in normal user environments.
il2cppHashGameAssemblybooltrueHashes GameAssembly.dll on Windows IL2CPP builds. This is the minimum recommended IL2CPP file guard.
il2cppHashGlobalGameManagersboolfalseAdds globalgamemanagers to IL2CPP coverage. The Standard and Strict presets turn this on because the file contains important Unity project settings.
il2cppHashSharedAssetsboolfalseAdds sharedassets* files to IL2CPP coverage. The Standard and Strict presets turn this on for broader asset tamper coverage.
il2cppHashSceneFilesboolfalseAdds Unity scene files such as level* to IL2CPP coverage. The Standard and Strict presets turn this on to catch scene-level tampering.
il2cppHashResourcesAssetsboolfalseAdds resources.assets to IL2CPP coverage. Useful in Strict mode, but test patch workflows first.
il2cppAdditionalWatchedFilesList<string>Additional Windows IL2CPP output files to include in manifest hashing when your project has custom native payloads.
blockEmulator (Android)booltrueAndroid only. Treats emulator or unsupported runtime signals as integrity violations.
blockSystemRwMount (Android)booltrueAndroid only. Treats writable system partitions or root-like mount state as an integrity violation. The Standard preset relaxes this to reduce QA false positives on unlocked or rooted test devices.
androidShaKeysList<string>Allowed SHA-256 fingerprints for APK/AAB signing certificates. Leave empty to skip this check; include both debug and release keys if development builds must pass.
expectedBundleIds (iOS)List<string>Allowed iOS bundle identifiers. Leave empty to skip the bundle ID check.
excludedAssembliesList<string>Assembly names without .dll to exclude from manifest generation and runtime hash verification. Unity/Mono framework assemblies are excluded automatically.
checkIntegrityWithServer (Pro)boolfalseEnables the Pro nonce -> attest flow. After local Build Integrity passes, the SDK submits build integrity evidence to OZero. With attestationVerificationMode=OZeroManaged, the optional OZero TMP dialog package, and a built-in Managed Verification UI, no game code is needed for the user-facing verification flow.
attestationVerificationMode (Pro)enumCustomerGameServerChoose who makes the final verdict for the OZA token. OZeroManaged lets the SDK ask OZero for a managed client-session verdict, so teams without a backend can use server attestation with the built-in UI. CustomerGameServer is for projects whose backend validates the OZA token through OZero APIs.
attestationNetworkPolicy (Pro)enumBestEffortControls what happens when fresh server revalidation is required but the network or server is unavailable. With OZeroManaged and the built-in UI, RequireOnlineRevalidation surfaces the online-required, retry, timeout, and blocked states through the SDK dialog automatically.
manifestSigningPublicKeystring""Base64 RSA-2048 public key used to verify the signed Build Integrity manifest. Generate it from Window > OZero Security > Config & Dashboard with Generate Key Pair. This is separate from the customer-portal server key used by OZeroLicenseConfig.
requireManifestSignatureboolfalse*Inspector default is off for development before keys are generated. In release player builds, manifest signature verification is forced on; generate a key pair before release.
manifestSigningPrivateKeyPathstring""Editor-only path to the private key PEM used at build time. If left empty, OZero uses [ProjectRoot]/OZeroSigningKeys/manifest_private_key.pem. This path is not included in player builds.

OZero server attestation with the default UI

For the no-code flow, enable checkIntegrityWithServer, set attestationVerificationMode to OZeroManaged, import the optional OZero TMP dialog package, and keep the Managed Verification UI policy in General Settings on a built-in dialog. The SDK obtains the nonce, submits attest evidence, asks OZero for a managed session verdict, and shows network-required, retry, timeout, warning, or blocked states through the default dialog. Register RegisterUserManagedVerificationStateCallback when replacing the default UI, avoiding TextMeshPro, or adding your own telemetry/session gate.

💡 Tip: Protect live builds with a stronger policy

Pro Strict Attestation is a stronger mode that can be enabled from the Pro policy in the customer portal. In this mode, the OZero server does not issue an OZA token immediately; it first checks whether the request comes from an active build registered in the portal. It also verifies that the submitted nonce, manifest hash, platform, SDK version, and app identity belong to the same request flow. Debugger, platform, speedhack, and injection checks must be clean, and at least one assembly/file/IL2CPP hash must be verified. If the conditions are not met, no OZA token is issued, so register the build version and manifest hash in the customer portal before releasing a new build.

Events

Event Description
OnValidationPassed Fires when local integrity checks complete successfully. Pro server attestation may still be pending.
OnAttestationPassed Fires only after the Pro OZA attestation token is issued. Use this, or AttestationToken.IsValid(nowMillis), before game-server login, PvP, ranking, or currency flows.
OnValidationFailed Fires when the integrity check detects a violation. Also triggers the global onHackDetected event with ModulationType.BuildIntegrity.

Generate RSA Signing Keys (Build Integrity Manifest)

Build Integrity can add an RSA signature to the manifest generated at build time. The manifest contains the assembly hashes and file integrity information that the SDK will verify at runtime. In release builds, the SDK must also know that this manifest itself has not been replaced, so create the manifest signing key pair from Window > OZero Security > Config & Dashboard before shipping.

Why manifest signing matters

At build time, OZero signs the manifest with the private key. The private key is not included in the player build; only the public key stored in OZeroSecurityConfig is included. At runtime, the SDK uses that public key to check whether the manifest is still the one created during the build. If the signature is valid, the SDK uses that manifest as the trusted baseline for assembly and file hash checks. If the signature is missing or does not match, the manifest may have been replaced or edited, so Build Integrity treats it as a failure and follows your Response Settings.

Build Integrity Manifest Signing UI in the Unity Editor

Generating the key pair

  1. In the Unity Editor, select OZeroSecurityConfig in the Project window.
  2. In the Inspector, expand the Build Integrity section.
  3. Enable the Require Manifest Signature checkbox.
  4. Click the Generate Key Pair button.
  5. OZero generates an public-key signature key pair. The public key is written directly into OZeroSecurityConfig (stored in your Assets). The private key is saved to:
    [ProjectRoot]/OZeroSigningKeys/manifest_private_key.pem
  6. A confirmation dialog shows the private key location. Click OK to dismiss it.
Critical — private key safety
  • The private key file is stored outside the Assets/ folder so Unity does not include it in builds. Never move it inside Assets/.
  • Exclude OZeroSigningKeys/ from version control with .gitignore or svn:ignore. Committing the private key is a critical security risk.
  • Back up the private key to a secure location. Anyone with this file can create a valid Build Integrity manifest for your project.
  • If you lose the private key, already released builds continue to work. However, the next update can no longer sign a new manifest with the old key. Generate a new key pair, regenerate the integrity manifest, and ship a clean build. The public key, fingerprint, manifest, and signature must match, or Build Integrity verification can fail.

Custom private key path (CI/CD & teams)

The Manifest Signing Private Key Path field does not choose where Generate Key Pair creates a new key. It tells the build and validation tools where to read the PEM private key. Generate Key Pair creates the key at the project default path, then records that path in the config. For CI/CD or team builds, restore the same PEM to a secure path first, then point this field at that path.

  • CI/CD pipelines — Store the PEM in a CI secret and restore it right before the Unity build. The runner does not need to keep the key on disk permanently.
  • Team environments — Use a secure mount path or secrets manager that only release builders can access. Every release build machine must use the same PEM.

Validating an existing key pair

If you are unsure whether the private key on disk still matches the public key stored in OZeroSecurityConfig, click Validate Key Pair. OZero derives the public key from the PEM and compares it with the config. If they do not match, restore the matching private key or generate a new key pair, then rebuild cleanly.

When to re-generate the key pair
  • Private key is lost or compromised.
  • Validate Key Pair reports a mismatch (keys are out of sync).
  • Deliberately rotating keys as part of a scheduled security policy.

After re-generating, already released builds continue to work with their own embedded key and manifest. The next update build must use the new public key, fingerprint, manifest, and signature as one matching set. Regenerate the integrity manifest and ship a clean build.

Dual-fingerprint key rotation

The Generate Key Pair button stores the public key in OZeroSecurityConfig and records a fingerprint for that key in Assets/OZeroSDK/Scripts/Security/BuildIntegrity/OZeroManifestTrustAnchor.cs. At runtime the SDK checks that the public key in the asset still matches the trusted fingerprint before it accepts a signed manifest.

Two fingerprint slots

ExpectedPublicKeyFingerprintHex is the fingerprint for the key used by the current build. PreviousPublicKeyFingerprintHex is an optional transition slot. It does not replace manifest regeneration, and it is not a server-side key manager. The public key in OZeroSecurityConfig, the fingerprint, the manifest, and the signature still need to be generated as one matching set.

Safe rotation procedure

  1. Note the current fingerprint. Open Assets/OZeroSDK/Scripts/Security/BuildIntegrity/OZeroManifestTrustAnchor.cs and copy the value of ExpectedPublicKeyFingerprintHex into your clipboard or a temporary note.
  2. Move it into the previous slot. In the same file, paste the value into PreviousPublicKeyFingerprintHex (which is normally ""). Save.
  3. Generate the new key pair. Open Window > OZero Security > Config & Dashboard and click Generate Key Pair in Build Integrity. The new public key and Expected fingerprint are updated automatically. Keep the Previous value from step 2.
  4. Regenerate the integrity manifest and make a clean build. The new manifest and signature must be produced with the new private key.
  5. Keep a transition period. Existing released builds keep using their own embedded key and manifest. The Previous slot is a safety net for rollback or mixed-artifact cases while the new build rolls out. Choose the window based on your update speed, commonly 1-4 weeks.
  6. Clear the previous slot. Once telemetry confirms the old build is at 0%, set PreviousPublicKeyFingerprintHex = "" and ship one more SDK release. Rotation complete.
What the previous slot does

Old shipped builds do not need the new key to keep working. They already carry their own public key, fingerprint, manifest, and signature. The Previous slot is useful for the new release line during a controlled key rotation window. Keep it only as long as you need the transition, then clear it in a later release.

Troubleshooting

Start with the simple checks first: run Generate Key Pair if no key exists, run Validate Key Pair if a key exists, then regenerate the integrity manifest and make a clean build. Most issues come from one of these four items being out of sync: private key PEM, public key in OZeroSecurityConfig, fingerprint in OZeroManifestTrustAnchor, or the generated manifest/signature files.

Symptom 1 — release build aborts immediately on launch with reason code 0x0E (TRUST_ANCHOR_MISSING)

ExpectedPublicKeyFingerprintHex may be empty. Release builds fail closed when the fingerprint is missing. Fix: run Generate Key Pair, wait for Unity to recompile, then make a clean build. If the value is already filled, run Validate Key Pair and rebuild from an empty output folder.

Symptom 2 — build halts with "no manifest signing public key is configured" before compilation starts

The PreBuild validator (callbackOrder 51) caught that OZeroSecurityConfig.Integrity.ManifestSigningPublicKey is empty. Fix: open OZeroSecurityConfig in the Inspector → expand Build Integrity → click Generate Key Pair, then rebuild. Note: this check is skipped on Android / iOS (OS-level signing) and on IL2CPP Standalone (no per-DLL files to sign), so a missing key only blocks Mono Standalone targets.

Symptom 3 — runtime log: "Manifest signing public key does NOT match the pinned trust anchor fingerprint — APK appears to have been repacked with attacker-controlled keys"

The public key in OZeroSecurityConfig does not match the fingerprint in OZeroManifestTrustAnchor. This usually happens after restoring only part of a key pair or editing generated files manually. Fix: run Validate Key Pair. If it reports a mismatch, restore the matching PEM or generate a new key pair, regenerate the integrity manifest, and make a clean build. If this appears only in a distributed build, also check whether the build was repackaged.

Symptom 4 — the new build fails manifest verification after key rotation

One part of the rotated set is probably stale: public key, fingerprint, manifest, or signature. Fix: keep the old fingerprint in PreviousPublicKeyFingerprintHex only if you need a transition window, then run Validate Key Pair, regenerate the integrity manifest, clear the old build output, and build again.

Symptom 5 — local builds work, but CI builds fail with "private key not found" or sign with the wrong key

CI does not automatically have the local OZeroSigningKeys/manifest_private_key.pem file. Fix: store the PEM as a CI secret and restore it before the Unity build, either to the default path or to the custom path configured in Manifest Signing Private Key Path. Make sure every release runner uses the same PEM, then run Validate Key Pair once in the release environment.

Install Source Settings

Restricts the game to only run when installed from authorized stores or sources. Useful for preventing sideloaded or repackaged APKs.

Field Type Default Description
Activate Install Source bool true The Dashboard activation checkbox for the Install Source module. Internally this maps to useInstallSource.
allowGooglePlayStore bool true Permits installs from the Google Play Store.
allowSamsungGalaxyStore bool false Permits installs from the Samsung Galaxy Store.
allowAmazonAppstore bool false Permits installs from the Amazon Appstore.
allowHuaweiAppGallery bool false Permits installs from the Huawei AppGallery.
allowOneStore bool false Permits installs from ONE Store (Korea).
allowXiaomiGetApps bool false Permits installs from Xiaomi GetApps.
allowOppoAppMarket bool false Permits installs from the OPPO App Market.
allowVivoAppStore bool false Permits installs from the Vivo App Store.
allowADB bool false Permits installs via ADB (Android Debug Bridge). Enable only for internal testing.
allowDetectionFailedboolfalseAllows the game to continue when Android installer-package detection fails because the OS or JNI query was unavailable. Keep disabled in release builds.
allowUnknownSourcesboolfalseAllows installer packages that are not in the built-in or custom allowlist. Use only for regional stores after testing.
enableServerSync (Pro)boolfalseSends the detected installer package to the OZero server for allowlist validation and audit. Pro only.
customAuthorizedPackages List<string> Additional authorized installer package names (e.g. com.yourcompany.launcher).
reportViolationToCallback bool true Routes unauthorized install-source detections to the SDK response callback/security manager path.
logRawInstallerPackage bool true Logs the raw installer package name to the console. Useful during development to identify the correct package name for a custom store.

Steam Anti-Piracy Settings

Checks Steam launch path, App ID, entitlement state, and release hygiene for PC builds distributed through Steam. Standard performs local validation; stronger ownership verification through Steam server evidence is provided by Pro server Steam Attestation.

Field Type Default Description
Activate Steam Anti-PiracycheckboxOffActivation checkbox for Steam Anti-Piracy. It is off by default because Steam App ID and distribution flow are project-specific. First verify the status in observe/QA mode, then tighten the release-build policy.
expectedSteamAppIdint0Your project’s Steam App ID. If you used development AppID 480 for local checks, replace it with the real App ID before release.
requireSteamLaunchbooltrueChecks whether the game was started through Steam rather than direct executable launch. Keep development direct-run tests separate from release policy.
requireSteamApiInitbooltrueChecks whether Steam API initialization succeeds. Local development launches can fail depending on Steamworks setup, so final judgement should be verified through the actual Steam distribution path.
requireSubscribedCurrentAppbooltrueChecks whether the current Steam account owns or is entitled to the app. This is local validation; server-side ownership verification is handled by Pro.
requiredDlcAppIdsList<int>Steam DLC App IDs whose ownership should be checked. Add the App ID for each paid or required DLC.
blockSteamAppIdTxtInReleasebooltruesteam_appid.txt is a development-only file for local launch testing without Steam. If it remains in a release build, OZero treats it as a violation because it can allow Steam-bypass launches. Remove it from the project root and build output before distribution.
validateSteamApiDllHashboolfalseOptionally validates the Steam API DLL hash against known-good SHA-256 values.
allowFamilySharing / allowFreeWeekend / allowTimedTrialbooltrueControls whether Steam family sharing, free weekend, and timed trial entitlement states are accepted.
requireSteamBuildIdNonZeroboolfalseTreat the build as invalid if Steam reports Build ID 0 or cannot provide a Build ID. Enable this after your Steam depot/build release flow is confirmed.
expectedSteamApiDllSha256HashesList<string>Allowed SHA-256 hashes used when validateSteamApiDllHash is enabled. Add the hash for each Steamworks SDK version, platform, or release branch you ship.
requireValveSignedSteamApibooltrueRequires the Steam API redistributable to match Valve platform identity. Windows uses Authenticode signer validation, macOS uses Valve Team ID validation, and other platforms should use SHA-256 validation as the fallback identity check.
detectKnownSteamEmulatorsbooltrueLooks near the executable for files or folders commonly left by Steam emulators such as Goldberg, CreamAPI, SmartSteamEmu, and ColdClientLoader. If one is found, OZero treats the launch as suspicious.
requireSteamEnvironmentConsistencybooltrueIn release builds, checks that Steam returns a valid individual SteamID and a non-zero Build ID. Preflight client/library path checks are logged as warnings, while invalid SteamID or Build ID becomes a violation.
observeSteamAuthTicketHeuristicbooltrueChecks only the size and basic shape of a local Steam auth ticket as a reference signal. OZero does not log ticket bytes, and this check never blocks the game by itself.
detectionActionOZeroSteamDetectionActionCallbackDecides how far the SDK should go when Steam validation fails. Observe records diagnostics only, Callback calls the game callback, and Block treats the event as a blocking policy. Actual app exit still follows Global Threat Response.
reportViolationToCallbackbooltrueWhen Steam validation fails in Callback mode, sends the event to the normal OZero security callback. Turn this off only for QA builds where you want logs but no game callback.
forceSteamAntiPiracyObserveOnlyboolfalseTemporarily records Steam failures as diagnostics only, without callback or block behavior. Use it while testing unusual Steam launch environments, then turn it off before release.
checkSteamDrmWithServer (Pro)boolfalsePro only. Enables server-backed Steam DRM verification. Use it when Steam ownership should be checked with server evidence instead of relying only on local Steamworks state.
steamDrmVerificationMode (Pro)OZeroSteamDrmVerificationModeOZero ManagedChoose who owns Steam DRM attestation. OZeroManaged lets the SDK call OZero /v1/steam/attest directly, manage the activation cache, and route user-facing states to the default Managed Verification UI after the optional OZero TMP dialog package is imported. CustomerGameServer means your server receives the OZA token and Steam ticket from the client, then calls OZero server APIs.
steamDrmNetworkPolicy (Pro)OZeroSteamDrmNetworkPolicyBest EffortControls what happens when fresh server revalidation is required but the network or server is unavailable. With OZeroManaged and the imported built-in UI package, RequireOnlineRevalidation shows the online-required and retry flow without game code.
For Standard Steam Anti-Piracy release builds, use IL2CPP where Unity supports it, keep Build Integrity enabled with the Standard or Strict preset, confirm that the manifest trust-anchor fingerprint is pinned, and rerun Tools > OZero Security > Steam Anti-Piracy > Scan Steam Redistributable whenever Steamworks SDK files change. Treat compatibility diagnostics such as unsupported accessors, non-standard library paths, or verification-unavailable states as QA signals first, not as proof of piracy by themselves.
When Steam Activation / DRM uses OZeroManaged, the first protected launch obtains a valid activation token online through OZero. After that, valid cached tokens and offline grace can allow offline play. If the token has expired, grace has ended, or revalidation is required while the user is offline, the default Managed Verification UI handles the online-required notice, Retry button, retry timeout, and blocked state automatically after OZeroSecurity_BuiltInDialog_TMP.unitypackage is imported.

OZero server-managed Steam DRM

Enable checkSteamDrmWithServer, set steamDrmVerificationMode to OZeroManaged, import OZeroSecurity_BuiltInDialog_TMP.unitypackage, and keep the Managed Verification UI policy in General Settings on a built-in dialog. The SDK sends the Steam auth ticket to OZero, manages the activation token cache, and presents online-required, retry, timeout, warning, or blocked states through the default UI. No callback or retry code is required unless you intentionally replace the built-in UI.

Customer game-server Steam verification

Enable checkSteamDrmWithServer and set steamDrmVerificationMode to CustomerGameServer. The client sends the OZA token and Steam auth ticket to your server. Keep Steam Web API Key and OZero Server API Key on the server, and retry your own login/session request after the player reconnects.

Device Binding Settings

Stores a fingerprint for the first trusted device and compares later launches against it. This helps detect when the same account or protected save data is moved to a different device.

How to use it in operations

In Pro, Device Binding becomes an operations tool. The server can remember which device fingerprints belong to a license, block devices that repeatedly show risk, and help support legitimate device changes without disabling the whole license.

Block devices with repeated risk

Use this after reviewing evidence from Security Events such as SpeedHack, Injection, Install Source, or Build Integrity. A blocked device receives DEVICE_BLOCKED on the next activation, device registration, device verify, or policy check.

Support legitimate device changes

Use a Reset Token when a real player changes phones, reinstalls the OS, replaces hardware, or hits a fingerprint mismatch after a normal environment change. The token is valid for 5 minutes, can be used once, and is bound to the exact license and device.

Limit registered devices

For Pro licenses, maxDevices limits how many active device fingerprints can be registered for one license. A blocked fingerprint does not automatically become a safe reusable slot; reset or delete it only after support verification.

Reset Token support flow

  1. Confirm the player account and why the device reset is needed through your normal support process.
  2. Open Customer Portal → Device Binding, select the target device, and issue a Reset Token.
  3. Send the token only through an authenticated support channel. Do not leave it in public chat, screenshots, or long-lived tickets.
  4. Your game or support UI should pass the token to OZeroDeviceBindingDetector.Instance?.ClearStoredFingerprint(token.Trim()).
  5. After the SDK accepts the token, restart the app or run the protected startup flow again. The current device fingerprint will be registered again.
Do not present Device Binding as a perfect proof of a real person or a permanent hardware identity. Platform identifiers can change after OS resets, privacy setting changes, or hardware replacement. For live games, describe it as an operations layer that raises sharing and abuse costs, and use it together with Build Integrity, Injection, SpeedHack, Install Source, and server validation.
Field Type Default Description
Activate Device Binding bool true Turns on Device Binding checks. When enabled, the SDK creates a local device fingerprint at startup and compares it with the stored value.
hardwareChangeTolerance int (0–3) 1 How many fingerprint components may change while still treating the device as the same device. 0 is strict, while 3 is more forgiving for major hardware or OS changes. The default 1 allows small OS or firmware changes.
storageKey string "ozero_dfp" PlayerPrefs key used by the SDK to store the encrypted local device fingerprint. Change it only if it conflicts with a key your game already uses.
enableServerSync (Pro) bool false Pro only. Registers the fingerprint with /v1/device/register on first use, then verifies it with /v1/device/verify on later sessions. Network or server outages do not block the game, but explicit server rejections such as DEVICE_BLOCKED, FINGERPRINT_MISMATCH, or DEVICE_LIMIT_REACHED are treated as Device Binding violations.
maxDevices (Pro)int0Shows the intended number of devices that may register for one license. 0 means unlimited. The real limit is enforced by the server license record or customer portal policy, so changing this client value alone does not raise the production limit.

Speed & Time Hack Settings

Detects time-scale manipulation (speed hacks) by comparing Unity Time.realtimeSinceStartup against native platform timers and optionally a trusted web time source.

Field Type Default Description
Activate Speed & Time Hack bool true Turns on Speed & Time Hack checks. When enabled, the SDK watches time ratios and device clock changes at runtime.
autoStart bool true Starts detection automatically on game launch. Disable to start manually via OZeroSpeedHackDetector.StartDetection().
checkInterval float 1.0 s How often the detector compares Unity time with the reference timers. Lower values react faster but may increase CPU cost and false positives.
requiredDetections int 3 How many abnormal samples must appear in a row before OZero treats the case as a violation. Increase this on unstable devices to reduce false positives.
ratioTolerance float 0.15 Allowed range used to check whether Unity time and the native timer drift abnormally. Start with the default value, then adjust only after testing false positives in your actual game environment.
maxAllowedRatio float 4.0 Maximum allowed time-flow ratio. If the ratio goes past this value, OZero treats it as a strong speed-hack signal without waiting for many samples.
detectSlowHack bool false Also detects tools that slow time down. Default is false; enable it only after testing normal slow motion, cutscenes, and intentional speed changes.
enableTimeScaleDetection bool true Checks whether Time.timeScale was changed by unapproved code or memory editing. Use OZeroTime.timeScale for intentional game-speed changes.
hackDetectMultiplier float 1.3 A sample far above maxAllowedRatio is counted as a stronger signal. Most projects should keep the default.
enableThreadTimerCheck bool true Uses a background thread timer as an additional reference clock, making it harder for hacks that only affect the main thread.
useWebTimeValidation bool true Cross-checks the device clock with HTTPS time responses or Pro signed server time. Default is true.
webSyncInterval float 15 s How often to compare against web or server time. Very short intervals increase network traffic.
webRatioTolerance float 0.15 Allowed range used to judge the difference between device time and web server time. Start with the default value and validate it with network latency and regional conditions in mind.
timeOffsetTolerance float 60 s Maximum absolute difference allowed between the device clock and web/server time before OZero treats it as time manipulation.
focusIgnoreTime float 4 s Seconds to ignore after the app regains focus (e.g. returning from multitasking). Prevents false positives when the OS freezes the app.
loadingGraceTime float 6 s Grace period after app startup or scene loading. It prevents heavy loading from being mistaken for time manipulation.
lagSpikeIgnore float 0.5 s Drops samples whose frame delta is larger than this value. This keeps real lag spikes from being counted as time manipulation.
buildFailIfTimeScaleTamperedbooltrueFails the build if protected code changes Time.timeScale outside the approved policy.
timeScaleTamperExemptionsList<string>Script or method name patterns that may directly change Time.timeScale. Keep this list as small as possible.
webTimeUrlsstring[]HTTPS addresses used for web/server time checks. Add two or more addresses you operate or trust so one blocked address does not stop the check.
minSuccessfulEndpointsint2Minimum number of addresses that must return a valid Date header before OZero trusts the time for that round.
maxConsecutiveFailuresint6Runs the unavailable policy after this many failed web/server time rounds in a row.
onWebTimeUnavailableWebTimeUnavailablePolicyWarnOnlyPolicy used when web/server time cannot be checked for several rounds. WarnOnly logs and continues, Strict raises a SpeedHack callback, and Silent should be reserved for special tests.
detectTimeHackbooltrueTurns on device-clock manipulation checks in addition to speed-ratio checks.
webSyncJitterPercentfloat20%Spreads web/server time checks around the configured interval so many clients do not call at the exact same moment.
sustainedLagThresholdfloat0.15If the recent average frame time is slower than this value, OZero treats it as real lag first and avoids confirming time-hack evidence immediately.
sustainedLagGraceDurationfloat3 sHow long OZero pauses strict timing judgment after sustained lag is detected. The pause is extended while lag continues, up to the runtime cap.
overloadStrictMultiplierint3In Strict mode, waits longer when failures look like timeout or overload rather than a clear server rejection.
enableRemoteSpeedHackConfig (Pro)boolfalseLets Pro server policy adjust selected Speed & Time Hack thresholds without an app update. If the server is unavailable, local Inspector values remain active.
remoteSpeedHackConfigIntervalfloat300 sHow often to refresh Pro remote Speed & Time Hack settings. 0 means fetch once at app startup only.
remoteSpeedHackConfigJitterPercentfloat20%Spreads Pro remote-config refresh timing so many devices do not call the server at the same moment.
enableSignedServerTime (Pro)boolfalseUses signed Pro /v1/time as the preferred trusted time source after Pro activation is available. Enable it after server keys and endpoint tests are complete.

Use OZeroTime.timeScale instead of Time.timeScale

When the Speed & Time Hack protection module is enabled, project code must not directly modify Unity's built-in Time.timeScale. If code bypasses OZero and writes to it directly, the OZero detector may treat the change as suspicious runtime time manipulation and run the configured response policy.

Exception policy (TimeScaleTamperExemptions)

OZeroSecurityConfig.TimeScaleTamperExemptions is an exception list for scripts that still need direct Time.timeScale access. Keep this list as small as possible.

Use exemptions only for verified third-party plugins or legacy adapter scripts where direct Time.timeScale access cannot be avoided because of the existing structure.

All other project gameplay code should use OZeroTime.timeScale without exception. Use it for pause, slow motion, cutscene speed control, fast-forward, and any other intentional game-speed changes.

using OZeroSDK.Security;

// Correct: the detector knows this is an intentional game-side change.
OZeroTime.timeScale = 0.5f;

// Avoid: this bypasses OZero's expected time-scale tracking.
Time.timeScale = 0.5f;
Before release, run Tools > OZero Security > Check Time.timeScale Usage and replace direct writes with OZeroTime.timeScale wherever possible.

Prevent unintended Watchdog termination during long loading

OZero's native Watchdog checks whether Unity's main thread is still alive by receiving periodic heartbeat updates. In release builds, non-Android platforms use about a 6-second heartbeat deadline, and Android uses about a 10-second deadline after startup grace. If no heartbeat arrives within that window, the app may be treated as stalled and terminated according to the configured response policy.

This can happen during legitimate work such as large scene loading, synchronous asset decompression, shader warmup, or Addressables preparation when the main thread is intentionally blocked for several seconds.

Wrap that trusted loading boundary with OZeroWatchdog.BeginLoadingGrace(maxGraceMs). The grace starts when loading begins and ends immediately when the scope is disposed or End() is called, so you do not need to know the exact loading time in advance.

using OZeroSDK.Security;
using UnityEngine.SceneManagement;

public void LoadLargeScene()
{
    using (OZeroWatchdog.BeginLoadingGrace(60000))
    {
        SceneManager.LoadScene("Battle", LoadSceneMode.Single);
        // Grace ends as soon as the using scope exits.
    }
}

public void WarmUpLargeAssets()
{
    OZeroWatchdog.RunWithLoadingGrace(() =>
    {
        BuildLargeRuntimeCache();
    }, 60000);
}
Caution: Do not misuse Loading Grace.

This feature is a temporary grace period that prevents the app from being terminated during long, legitimate loading work. It cannot be used for security bypasses or to keep the app running indefinitely.

If a heavy loading task may exceed the allowed time, split it into smaller steps or use Unity Coroutines / async loading so the screen and main thread do not stay frozen.

Physics Hack Detector

Attach this component to each moving player object.
OZeroSecurityConfig.PhysicsHack only controls the global on/off switch and Pro telemetry. Speed limits, distance tolerance, wall-crossing checks, and acceleration checks are configured on each OZeroPhysicsHackDetector component. Attach it to the player prefab, tune the values for the real movement rules of that character or vehicle, and call Initialize(playerId) after spawn.
Field Type Default Description
physicsHack.useGlobalPhysicsHackbooltrueGlobal on/off switch for all Physics Hack components. Turn it off only when you intentionally want every physics movement check to stop.
physicsHack.enableServerTelemetry (Pro)boolfalsePro only and disabled by default. This explicit project opt-in controls both general security-event telemetry and the detailed PhysicsHack stream. Turning it off stops new telemetry events, and a server policy can disable but never enable transmission without local consent.
physicsHack.telemetryThrottlePerMinute (Pro)int30Maximum number of PhysicsHack telemetry events this client can send per minute. This prevents a bad threshold from flooding the server.
Field Type Default Description
maxAllowedSpeed float 15 u/s Maximum normal movement speed for this object, in Unity units per second. Set it to the fastest legitimate speed this character or vehicle can reach in the game.
distanceTolerance float 2.0 u Extra distance allowed beyond the movement distance calculated from maxAllowedSpeed. Use it to absorb network position correction, physics rounding, and small controller jitter.
obstacleLayer LayerMask Layers treated as walls or solid obstacles. OZero checks the path from the previous safe position to the current position; if that path crosses one of these layers, it can be treated as wall clipping.
checkInterval float 0.05 s How often this component checks position, wall crossing, and acceleration anomalies. Lower values react faster but use more CPU.
maxDeltaTimeCap float 0.1 s Maximum frame time used in the distance calculation. This prevents one long frame from giving a cheater a very large allowed movement distance.
violationThresholdint2Number of bad checks required before the callback fires. A normal check lowers the counter, so one small physics glitch does not immediately become a violation.
castRadiusfloat0Radius used for wall-crossing checks. 0 lets OZero estimate it from a CharacterController or CapsuleCollider; if none is found, it falls back to a line check.
enableAccelerationCheckbooltrueChecks sudden Rigidbody speed changes. Consider disabling it for kinematic objects, server-authoritative movement, or custom movement that normally changes velocity outside the physics solver.
maxAllowedAccelerationfloat60Maximum speed change allowed between checks. Raise this for dash, knockback, launch pads, vehicles, or other legitimate burst movement.
enableLogbooltrueShows debug logs from this component while tuning. Serious setup issues, such as an empty obstacle layer, still warn even when this is off.

Injection & Hooking Settings

Detects suspicious native modules, executable private memory, inline hooks, remote-thread style injection, high-risk process handles, and WebGL runtime tampering signals.

Start with the default settings.
Add whitelist entries only when a normal overlay, recorder, partner DLL, or module shipped with your game is detected. First confirm the module path, file hash, and signer fingerprint from Failure Diagnostics or Pro telemetry. Do not use the whitelist to broadly allow random programs installed on a customer's PC.
Field Type Default Description
Activate Injection & HookingcheckboxOnDashboard checkbox that maps to useInjection. In player builds it enables the native injection checks; development builds use a softer diagnostic flow, and the Editor normally skips the detector.
injectionWhitelistEntriesOZeroInjectionWhitelistEntry[]emptyLocal trusted module list available in all tiers. Each entry allows one specific module by SHA-256 file hash and optional signer fingerprint. Add only modules shipped with the game or verified through QA, diagnostics, Pro telemetry, or OZero support.
enableServerWhitelist (Pro)boolfalsePro only. Downloads server-managed trusted module entries and merges them with the SDK baseline and local list. If the server is unavailable, the detector keeps using the last known local/baseline entries instead of turning protection off.
serverWhitelistRefreshIntervalfloat0 sHow often Pro server whitelist entries are refreshed. 0 means fetch once at startup only, which is enough for most projects because trusted module lists rarely change.
requireSignerForNativeWhitelistboolfalseRequires Windows PE and Apple Mach-O whitelist entries to include a signer fingerprint as well as the file hash. Stronger, but use it only after you can collect clean signer data. Android/Linux shared libraries remain hash-only.
enableRemoteInjectionConfig (Pro)booltruePro only. Lets the portal override selected Injection settings, such as scan intervals, signer requirements, and individual probe switches, without shipping a new app build.
remoteInjectionConfigIntervalfloat300 sHow often the Pro remote Injection config is checked again. 0 means the SDK fetches it only once during startup.
enableWindowsModuleIdentityScanbooltrueChecks newly loaded native modules against trusted identity data. The legacy field name says Windows, but supported native targets use the same setting; Windows/macOS can use hash plus signer, while Android/iOS/Linux usually use hash-only.
scanIntervalSecondsfloat1 sMain Injection scan interval. Lower values detect faster but add more runtime overhead. The runtime clamps this value to a safe range.
windowsModuleIdentityScanIntervalSecondsfloat5 sSeparate interval for the heavier native module identity scan. Increase it if module enumeration or hash/signer checks are too expensive on your target device.
scanJitterPercentfloat20%Spreads each periodic Injection check slightly around the configured interval. This keeps checks from running at an easy-to-predict exact second.
enableExecutablePrivateMemoryScanbooltrueDetects executable private memory that was not loaded as a normal module. This catches shellcode-style payloads, but may need QA if a trusted runtime creates executable memory on purpose.
enableInlineHookScanboolfalseChecks whether sensitive native API entry points look patched. This is useful for strict builds, but overlays and security software can hook APIs, so enable it only after compatibility testing.
enableThreadStartAddressScanbooltrueChecks whether a native thread starts from suspicious memory outside trusted loaded modules. This helps catch remote-thread style injection on supported platforms.
enableExternalProcessHandleScanbooltrueChecks for external processes holding high-risk handles to the game process, such as debugger or memory editor attach states. Supported mainly on Windows.
detectionConfidenceThresholdint70Minimum confidence score for a strong Injection signal to be treated as a violation immediately. Lower-confidence signals can still be handled by consecutive or sliding-window checks.
enableWebRuntimeTamperScan (WebGL)booltrueWebGL-only browser runtime checks. WebGL cannot use Native C++ module scanning, so these probes look for browser-side tampering signals and should be treated as supplementary client-side evidence.
webRuntimeScanIntervalSeconds (WebGL)float1.5 sBase interval for WebGL runtime checks. The runtime clamps it to 0.5-30 seconds so the browser is not checked too aggressively.
webRuntimeScanJitterPercent (WebGL)float20%Spreads WebGL runtime check timing around the configured interval so checks do not run at a perfectly predictable moment.
WebGL probesboolstrueIndividual WebGL probe switches for DevTools, clock hooks, network hooks, WebAssembly hooks, storage hooks, and crypto API hooks.

Encrypt PlayerPrefs

To protect values normally stored in Unity's PlayerPrefs, use OZeroSafePlayerPrefs for new protected keys. The common Get/Set, HasKey, Delete, and Save methods use familiar names, but encrypted data is not compatible with existing plain PlayerPrefs data.

using OZeroSDK.Security;

// Save a value
OZeroSafePlayerPrefs.SetInt("score", 4200);
OZeroSafePlayerPrefs.SetFloat("volume", 0.8f);
OZeroSafePlayerPrefs.SetString("username", "Hero");

// Read a value
int    score    = OZeroSafePlayerPrefs.GetInt("score", 0);
float  volume   = OZeroSafePlayerPrefs.GetFloat("volume", 1.0f);
string username = OZeroSafePlayerPrefs.GetString("username", "");

Encrypt Save Files

To encrypt save files, use OZeroSV_File instead of File.ReadAllText / File.WriteAllText. The file is automatically encrypted on write and decrypted on read. Tampering is detected on load.

using OZeroSDK.Security;

string path = Application.persistentDataPath + "/save.json";

// Write encrypted file
OZeroSV_File.WriteAllText(path, jsonString);

// Read and decrypt file
string json = OZeroSV_File.ReadAllText(path);
Important: do not change developerSecret after launch. It is the base value used to derive the encryption key for OZeroSafePlayerPrefs and OZeroSV_File data. If you change it after release, protected data saved by older versions cannot be decrypted by newer builds.

4 Protect In-Game Variables (Secure Types)

Secure Types replace ordinary C# variable types with encrypted equivalents. Values are stored in the Native C++ heap so tools like Cheat Engine cannot find them by scanning memory. The replacement is a simple name swap — all operators and implicit conversions work the same way.

Unity Inspector showing OZeroSV_Int and OZeroSV_Float fields

Example

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OZeroSDK.Security;

public class PlayerStats : MonoBehaviour
{
    [SerializeField] OZeroSV_Int Gold = 5000;
    [SerializeField] OZeroSV_Float Speed = 3.5f;
    [SerializeField] OZeroSV_Int HP = 1000;
}

Supported types

Before After (OZero)
intOZeroSV_Int
longOZeroSV_Int64
uintOZeroSV_UInt
ulongOZeroSV_UInt64
shortOZeroSV_Short
ushortOZeroSV_UShort
byteOZeroSV_Byte
floatOZeroSV_Float
doubleOZeroSV_Double
decimalOZeroSV_Decimal
boolOZeroSV_Bool
stringOZeroSV_String
Vector2OZeroSV_Vector2
Vector3OZeroSV_Vector3
byte[]OZeroSV_Buffer
Secure Types use the OZeroSDK.Security namespace. Add the using directive to any script that declares them.

7 Handle Security Events (Optional)

By default, OZero force-quits the application when it detects a threat (if Force Quit On Detection is enabled). If you prefer to handle threats yourself — for example, to show a warning screen, log the event to your server, or apply in-game penalties — you can register a callback.

using UnityEngine;
using OZeroSDK.Security;

public class SecurityHandler : MonoBehaviour
{
    void OnEnable()
    {
        // RegisterUserCallback runs on the user chain only.
        // The built-in default handler runs independently and cannot be silenced.
        OZeroSecurityManager.Instance.RegisterUserCallback(OnThreatDetected);
    }

    void OnDisable()
    {
        OZeroSecurityManager.Instance.UnregisterUserCallback(OnThreatDetected);
    }

    void OnThreatDetected(OZeroSecurityEvent evt)
    {
        // evt contains Type, AbortCode, AbortCodeHex, MessageKey, Message, and WillAbort.
        Debug.LogWarning(
            $"OZero threat: {evt.Type} {evt.AbortCodeHex} {evt.Message}");

        switch (evt.Type)
        {
            case ModulationType.SpeedHack:
                // e.g. kick the player, show warning, report to server
                break;

            case ModulationType.BuildIntegrity:
                // evt.WillAbort is usually true for fatal build integrity violations.
                break;

            case ModulationType.Injection:
                break;
        }

        if (evt.WillAbort)
        {
            // Last chance to flush your own analytics or save state.
        }
    }
}

The full list of ModulationType values is documented in the API Reference.

If you register a callback but still want force-quit as a fallback, keep Force Quit On Detection enabled in OZeroSecurityConfig. Your callback fires first, then the application exits.
Four independent defence paths

When a threat is detected, OZero first applies the SDK's default response policy and also sends the same security event to callbacks and Inspector events registered by the project. Register a callback if you want to show your own warning screen or write server logs. Whether the app will close can be checked through the Config Dashboard Response settings and evt.WillAbort.

Portal policy callback

Customer Portal policies can be operated in stages. Observe only records evidence, Callback sends a server-issued policy action to the game, and Device Block blocks the selected device on later server verification. Use Callback when you want the game to show a warning, limit matchmaking, request re-login, or route the player to support before using a stronger device block.

using UnityEngine;
using OZeroSDK.Security;

public class PolicyActionHandler : MonoBehaviour
{
    void OnEnable()
    {
        OZeroSecurityManager.Instance.RegisterUserPolicyActionCallback(OnPolicyAction);
    }

    void OnDisable()
    {
        OZeroSecurityManager.Instance.UnregisterUserPolicyActionCallback(OnPolicyAction);
    }

    void OnPolicyAction(OZeroPolicyActionEvent evt)
    {
        Debug.LogWarning(
            $"Policy callback: {evt.Module}, score={evt.Score}, reason={evt.Reason}");

        if (evt.Score >= 80)
        {
            // Show your own UI, limit sensitive actions, or ask the player to reconnect.
        }
    }
}

Next Steps

You now have the core OZero protection running. Explore the full API Reference to learn about every class, method, and configuration option in detail.