Overview
Sand Blocks is a portrait drag puzzle with 500 levels. Glass tanks at the top of the board hold coloured sand in layers; every tank column pours its bottom layer straight down into the box that rests under it. Drag the open boxes on the board (they slide through free cells only) under a column whose bottom sand matches their colour: the sand pours in, the full box pops and frees its cells. Fill every box before the countdown reaches 00:00 to win; at 00:00 the level is lost. Level 1 is a guided tutorial with the shared tutorial hand.
Mechanics introduced over the campaign: layered tank columns (level 5), numbered covers that open after that many boxes have been filled (level 10), boxes hidden under closed covers (level 15), key boxes that open the padlocked box (level 40) and pipe-fed tanks (level 60), on nine board families (twin tanks, corridors, steps, pillars, channels, covered boards, towers, pockets and vaults). Every 50th level is a SUPER HARD level. Levels 1 and 200 are the two recorded boards of the original game.
The HyperCasualLiveOpsKit (separate root Assets/HyperCasualLiveOpsKit, with its own guide) supplies the menu, level selection, capsule HUD, results, wallet, quests, pass, minigames, shop (LocalQA dummy store), ads (LocalQA mock) and the booster bar with refills.
Getting Started
- Create a Unity 6000.0.62f1 project with the Universal Render Pipeline, the Input System (set Active Input Handling to Both or Input System) and uGUI; import TextMesh Pro Essential Resources when Unity asks.
- Import the package. Assign
Assets/Game/ProjectRenderSettings/PC_RPAsset.asset(orMobile_RPAsset.asset) in Graphics and Quality settings and use the Linear colour space. - Add
Assets/HyperCasualLiveOpsKit/StarterMenu/Scenes/HLK_MainMenu.unity(first) andAssets/Game/Scenes/Game.unityto the build settings and press Play in the menu scene. Choose a level or press PLAY NEXT LEVEL. - Open Tools → Sand Blocks → Level Editor or Auto Level Generator to inspect and change the campaign, and Tools → Sand Blocks → Documentation for this guide.
Folder Structure
| Folder | Contents |
|---|---|
Game/Scripts/Core | Pure C# rules: LevelData (the level JSON contract), Sim (fixed 60 Hz simulation of dragging, pouring, completion, covers, keys/padlock, countdown), SimBoosters (freeze, hammer, UFO), Contract (recorded-level contracts). |
Game/Scripts/Core/Campaign | The generator: CampaignPlan (introductions, family schedule, per-level request), Families (board layouts), LevelBuilder (forward construction with a witness), CampaignGenerator, Witness (WitnessMove, WitnessReplay), Solver (independent policy), Footprints, LevelJson. |
Game/Scripts/Game | Presentation: GameController (input, level start, host hooks), Viewport (camera and host framing), WorldView, BoardView, PieceView, SandStreamView, FxView, BoosterView, AudioView, Session (level catalogue). |
Game/Scripts/UI | The game's own HUD (countdown plate, SUPER HARD banner and the standalone menu/result screens). |
Game/Scripts/Models | The model registry and procedural/native model variants used by the board and boxes. |
Game/Integration | The link to the kit: SandBlocksHlkBridge (level selection, pointer/modal gating, one settlement per attempt, results, analytics, play area), SandBlocksPowerUpAdapter (freeze/hammer/UFO on the kit bar), SandBlocksBoosterProgression, SandBlocksPointerDriver, booster definitions in PowerUps. |
Game/LevelTools, Game/ProductionLevelTools | Editor-only level editor and generator (Sand Blocks adapter on the shared level-tools framework) and its baseline data. |
Game/Resources/Levels | The playable campaign Level_1.json … Level_500.json and CampaignAuthoring.json (authoring data, never counted as a level). |
Game/Resources/LevelSources | The two recorded boards level-1.json and level-200.json as originally authored. |
Game/Resources (other) | Native and generated models, materials, shaders, images, audio, Unity-provided default fonts and the booster progression policy (HLK/BoosterProgression.json). |
Game/Scenes, Game/ProjectRenderSettings | The gameplay scene and the URP assets. |
Gameplay
Moving. Press a visible box and drag: it follows the finger through free cells (it collides with other boxes, walls, closed covers and the board edge) and snaps to the nearest cell on release. One box is held at a time. A box under a closed cover cannot be picked up; a press on it counts as a blocked attempt.
Pouring. Each tank column pours its bottom sand layer into the box on its dock cell (the cell below the column; the outermost columns also feed the cell beside the tank's bottom row). The colour must match. A box fills at the level's fillPctPerSec, split over the columns feeding it, and the sand leaves those columns' queues; when a layer runs out the next colour above it reaches the bottom.
Covers, keys, padlock. A cover shows a number: every filled box lowers it by one; at zero the cover rolls away and the boxes under it can be moved. Filling a key box sends its key to the padlocked box; when all keys have arrived, the padlock opens and that box can receive sand.
Outcome. Filling every box wins (the kit results credit the win reward once, default 50 coins). The countdown (90–240 s per level) reaching 00:00 loses; the lose card offers TRY AGAIN. Every campaign level has a stored solution (witness) that wins in the simulation with at least 61 s to spare.
Scripts Reference
| Type | Role |
|---|---|
SandBlocks.Core.LevelData | Parses the level JSON (FromJson, Validate); LevelJson.ToJson writes it. |
SandBlocks.Core.Sim | Deterministic simulation: PointerDown/Move/Up, Step, Legal, Hidden, events (grab, drop, complete, unlock, cover-open, won, lost) and booster effects (UseBooster, CanTarget). |
SandBlocks.Core.WitnessMove, WitnessReplay, Solver | The stored solution (a list of box drags with their cell paths), its proof through the Sim (Play) and an independent search policy (Solve). |
SandBlocks.Core.CampaignGenerator, CampaignPlan | The saved progression plan (introductions, family schedule, recovery and SUPER HARD levels) and Generate(index, family, seed, …); every slot is reproducible on its own. |
SandBlocks.Game.GameController | Starts levels (StartLevel, Restart), turns pointer input into Sim input, exposes LevelStarted, OnSimEvent, PressRefused and the host hooks. |
SandBlocks.Game.Viewport | Camera. Under the kit the board is fitted full-window into HostPlayArea (SolveHost, FrameHost). |
SandBlocks.Integration.SandBlocksHlkBridge | Kit link: selected level, one settlement per attempt, results, sandblocks_level_end analytics (level, won, coins, moves, fills, blocked, seconds), PlayArea(). |
Level Editor
Tools → Sand Blocks → Level Editor lists the campaign on the left (duplicate, delete, move up/down, Undo). The canvas draws the board as the game lays it out: tanks with their sand layers (the bottom layer pours first), dock marks under each tank column, board cells, walls, numbered covers and every box in its colour and footprint with key/padlock marks.
- Box: pick a footprint (1x1, 1x2, 1x3, 1x4, 2x2, L3, L4), a quarter turn, mirror and colour, then click a free cell; click a box to remove it.
- Cell adds/removes board cells (notches, bays), Wall toggles a wall on an empty board cell, Cover adds/removes a cell of the selected cover and sets its count, Key/Lock cycles a box through key → padlocked → plain.
- Rebuild sand + witness re-derives the tank layers and a witness for the edited board with the generator's construction (proven on the Sim; try another seed when it fails); Solve searches a witness for the current data with the policy solver; Check validates and replays it.
Every edit clears the level's stored witness. Saving refuses levels without a proven witness, invalid layouts and duplicate puzzles, and leaves the published JSON unchanged on failure. Play saved level opens it in the game scene.
Automatic Level Generator
Tools → Sand Blocks → Auto Level Generator (same window) saves the generation request (final count, seed, attempts, minimum formations, repeat streak, append) and generates into the editor for review before saving. Generation is deterministic per seed and slot: each board is built forward from its solution — the generator lays out the family's tanks and board, places the boxes, then plays the planned delivery order to derive which sand each column holds, so every board is solvable by construction and its witness is replayed on the Sim. Slots 1 and 200 keep the recorded boards. Append mode keeps the existing levels and adds new ones after them; cancelling leaves the campaign unchanged. A 500-level run takes about three minutes in the editor.
Boosters
| Booster | Unlock | Effect |
|---|---|---|
| Freeze | Level 2 | Stops the countdown for 10 s. |
| Hammer | Level 7 | Tap a visible box: it fills at once; its sand is taken from the tanks. |
| UFO | Level 12 | Tap a visible box: every box of that colour fills and that colour's sand leaves the tanks. |
Each unlock grants two free charges once. Refills cost 100 + 25 × floor((highest level − 1) / 10) coins or a rewarded ad (LocalQA mock). The policy is Game/Resources/HLK/BoosterProgression.json. The first use shows the booster explanation; a targeted booster then guides its first tap with the shared tutorial hand on a valid box. Taps on covered boxes are not targets and cost nothing.
Level Variation
Families: twin tanks (from level 2), corridor (3), step (5), pillar (7), channels (10), covered boards (15), towers (20), pocket (25) and vault (40). The opening 2–40 introduces one idea at a time; afterwards a seeded schedule never shows a family three times running. Boxes grow from 2–6 per board in levels 1–10 to about 12 on average late in the campaign (up to 28), colours from 2 to 9. Levels ending in 8 (from 28) are lighter recovery boards; every 50th level is SUPER HARD. A rectangle-silhouette rule shapes every third board (narrow tanks, notched corners, comb walls). The current campaign has 320 distinct geometries; the historical variety audit (path silhouettes 124, combined structures 325, no similar board or path run longer than two) passed.
Customization Guide
- Timing and rewards: the countdown per level is each level's
timerSeconds; the kit's win reward isStarterMenuConfig.WinCoinReward(the level's ownrewardis used only by the game's standalone result screen). - Pour speed: each level's
fillPctPerSec(percent of a box per second). - Board framing:
Viewport.MaxCellFractionandViewport.SolveHost; the area isSandBlocksHlkBridge.PlayArea(). - Colours: the palette is in
LevelBuilder.PaletteHexand the per-levelpalettetable; box and sand art comes from the existing models and materials. - Progression: edit
CampaignPlan.Introductions, the opening table orPlan, then regenerate with the tools (the recorded slots are preserved). - Boosters: unlock levels, grants and prices in
BoosterProgression.json.
Level Format
Each Level_N.json holds the grid (cols, rows), the playable board cells and walls, the boxes (pieces: id, colour, absolute cells, footprint shape, rot, mirror, optional key / locks), the tanks (reservoirs: cells, pipe, and per column the sand queue from the bottom layer up as [colour, box cells]), the covers (cells and count), the countdown, pour speed, palette, the board family, the slot index and the proven witness. Level 18, shortened:
{
"id": "Level_4",
"number": 4,
"title": "Level 4",
"grid": {
"cols": 4,
"rows": 6
},
"playable": [
[
0,
2
],
[
1,
2
],
[
2,
2
],
[
3,
2
],
[
0,
3
],
[
1,
3
],
[
2,
3
],
[
3,
3
],
[
0,
4
],
[
1,
4
],
[
2,
4
],
[
3,
4
],
[
0,
5
],
[
1,
5
],
[
2,
5
],
[
3,
5
]
],
"walls": [],
"pieces": [
{
"id": "b1",
"colour": "yellow",
"cells": [
[
3,
4
]
],
"shape": "box-1x1",
"rot": 0,
"mirror": false
},
{
"id": "b2",
"colour": "darkgreen",
"cells": [
[
2,
2
],
[
3,
2
]
],
"shape": "box-1x2",
"rot": 0,
"mirror": false
},
{
"id": "b3",
"colour": "yellow",
"cells": [
[
2,
4
]
],
"shape": "box-1x1",
"rot": 0,
"mirror": false
},
{
"id": "b4",
"colour": "darkgreen",
"cells": [
[
1,
2
]
],
"shape": "box-1x1",
"rot": 0,
"mirror": false
},
{
"id": "b5",
"colour": "darkgreen",
"cells": [
[
1,
3
]
],
"shape": "box-1x1",
"rot": 0,
"mirror": false
}
],
"reservoirs": [
{
"id": "T1",
"cells": [
[
0,
0
],
[
1,
0
],
[
0,
1
],
[
1,
1
]
],
"pipe": "none",
"columns": [
{
"col": 0,
"queue": [
[
"darkgreen",
2
]
]
},
{
"col": 1,
"queue": [
[
"yellow",
2
]
]
}
]
},
{
"id": "T2",
"cells": [
[
2,
0
],
[
3,
0
],
[
2,
1
],
[
3,
1
]
],
"pipe": "none",
"columns": [
{
"col": 2,
"queue": [
[
"darkgreen",
1
]
]
},
{
"col": 3,
"queue": [
[
"darkgreen",
1
]
]
}
]
}
],
"covers": [],
"timerSeconds": 180,
"coins": 0,
"reward": 40,
"doubleReward": 0,
"featurePct": 0,
"featureTitle": "New Feature!",
"featureIcon": "silhouette",
"introSeconds": 0,
"timerStartDelay": 0,
"fillPctPerSec": 100,
"boostersLockedBar": false,
"palette": {
"white": "#EEF0FA",
"black": "#34323A",
"purple": "#8A3CF0",
"darkgreen": "#15806A",
"orange": "#F2821E",
"yellow": "#FAD21E",
"blue": "#2E6CF0",
"green": "#2ED85A",
"red": "#EC3C48",
"pink": "#E64EE6"
},
"index": 4,
"family": "twin",
"witness": [
{
"piece": "b5",
"relocation": false,
"path": [
[
0,
3
],
[
0,
2
]
]
},
{
"piece": "b4",
"relocation": false,
"path": [
[
0,
2
]
]
},
{
"piece": "b3",
"relocation": false,
"path": [
[
1,
4
],
[
1,
3
],
[
1,
2
]
]
},
{
"piece": "b1",
"relocation": false,
"path": [
[
2,
4
],
[
1,
4
],
[
1,
3
],
[
1,
2
]
]
}
]
}Support
Questions and bug reports: satisvizion@gmail.com. Please include the Unity version, the level number and the editor console output.
Licences and Notices
Historical Lilita One notice (retired font, not a current packaged dependency; verbatim)
Copyright (c) 2011 Juan Montoreano (juan@remolacha.biz), with Reserved Font Name Lilita This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
The packaged Third-Party Notices.txt records the verified dependency inventory and unresolved provenance. Owner confirmation of original supplied asset rights remains required.
Current delivery and examples
Unity 6000.0.62f1 / URP. Support: satisvizion@gmail.com.
Buyer roots: Assets/Game, Assets/HyperCasualLiveOpsKit. Internal production, build and upload folders are excluded. The kit is an owner-approved first-party asset.
Current campaign: 500 levels. Use the shipped Level Editor and Auto Level Generator menu entries: Tools/Sand Blocks/Documentation, Tools/Sand Blocks/Level Editor, Tools/Sand Blocks/Auto Level Generator.
Current complete level example
Assets/Game/Resources/Levels/Level_4.json
{
"id": "Level_4",
"number": 4,
"title": "Level 4",
"grid": {
"cols": 4,
"rows": 6
},
"playable": [
[
0,
2
],
[
1,
2
],
[
2,
2
],
[
3,
2
],
[
0,
3
],
[
1,
3
],
[
2,
3
],
[
3,
3
],
[
0,
4
],
[
1,
4
],
[
2,
4
],
[
3,
4
],
[
0,
5
],
[
1,
5
],
[
2,
5
],
[
3,
5
]
],
"walls": [],
"pieces": [
{
"id": "b1",
"colour": "yellow",
"cells": [
[
3,
4
]
],
"shape": "box-1x1",
"rot": 0,
"mirror": false
},
{
"id": "b2",
"colour": "darkgreen",
"cells": [
[
2,
2
],
[
3,
2
]
],
"shape": "box-1x2",
"rot": 0,
"mirror": false
},
{
"id": "b3",
"colour": "yellow",
"cells": [
[
2,
4
]
],
"shape": "box-1x1",
"rot": 0,
"mirror": false
},
{
"id": "b4",
"colour": "darkgreen",
"cells": [
[
1,
2
]
],
"shape": "box-1x1",
"rot": 0,
"mirror": false
},
{
"id": "b5",
"colour": "darkgreen",
"cells": [
[
1,
3
]
],
"shape": "box-1x1",
"rot": 0,
"mirror": false
}
],
"reservoirs": [
{
"id": "T1",
"cells": [
[
0,
0
],
[
1,
0
],
[
0,
1
],
[
1,
1
]
],
"pipe": "none",
"columns": [
{
"col": 0,
"queue": [
[
"darkgreen",
2
]
]
},
{
"col": 1,
"queue": [
[
"yellow",
2
]
]
}
]
},
{
"id": "T2",
"cells": [
[
2,
0
],
[
3,
0
],
[
2,
1
],
[
3,
1
]
],
"pipe": "none",
"columns": [
{
"col": 2,
"queue": [
[
"darkgreen",
1
]
]
},
{
"col": 3,
"queue": [
[
"darkgreen",
1
]
]
}
]
}
],
"covers": [],
"timerSeconds": 180,
"coins": 0,
"reward": 40,
"doubleReward": 0,
"featurePct": 0,
"featureTitle": "New Feature!",
"featureIcon": "silhouette",
"introSeconds": 0,
"timerStartDelay": 0,
"fillPctPerSec": 100,
"boostersLockedBar": false,
"palette": {
"white": "#EEF0FA",
"black": "#34323A",
"purple": "#8A3CF0",
"darkgreen": "#15806A",
"orange": "#F2821E",
"yellow": "#FAD21E",
"blue": "#2E6CF0",
"green": "#2ED85A",
"red": "#EC3C48",
"pink": "#E64EE6"
},
"index": 4,
"family": "twin",
"witness": [
{
"piece": "b5",
"relocation": false,
"path": [
[
0,
3
],
[
0,
2
]
]
},
{
"piece": "b4",
"relocation": false,
"path": [
[
0,
2
]
]
},
{
"piece": "b3",
"relocation": false,
"path": [
[
1,
4
],
[
1,
3
],
[
1,
2
]
]
},
{
"piece": "b1",
"relocation": false,
"path": [
[
2,
4
],
[
1,
4
],
[
1,
3
],
[
1,
2
]
]
}
]
}Level fields
| Field | JSON type |
|---|---|
| id | str |
| number | int |
| title | str |
| grid | dict |
| playable | list |
| walls | list |
| pieces | list |
| reservoirs | list |
| covers | list |
| timerSeconds | int |
| coins | int |
| reward | int |
| doubleReward | int |
| featurePct | int |
| featureTitle | str |
| featureIcon | str |
| introSeconds | int |
| timerStartDelay | int |
| fillPctPerSec | int |
| boostersLockedBar | bool |
| palette | dict |
| index | int |
| family | str |
| witness | list |
Safe worked editing procedure
- Open Level 4 in the Level Editor and duplicate it into an unused slot.
- Use the editor’s supported controls for a small placement change; keep legal occupancy and required targets. Do not invent JSON fields.
- Run the shipped validator, correct any rule errors, save, then open the duplicate in gameplay and complete it.
- For generation, record the current seed, request a small append batch using the exposed controls, validate its solutions and confirm the previous campaign prefix is unchanged. Cancelling must leave the campaign unchanged.
Run these procedures in a clean import of the final candidate before claiming buyer acceptance; restore test additions afterward.
Current booster policy
{
"schemaVersion": 1,
"gameId": "sand-blocks",
"defaultProfileId": "default",
"initialGrant": 2,
"refillAmount": 1,
"baseCoinCost": 100,
"coinCostStep": 25,
"levelsPerPriceStep": 10,
"rewardedTimeoutSeconds": 90,
"boosters": [
{
"id": "sandblocks_freeze",
"unlockLevel": 2,
"rewardedPlacementId": "booster_refill_sandblocks_freeze",
"reason": "Module 04 default first unlock (level 2). Instant and always useful: every level runs on the countdown; teaches the booster shelf without a targeting step. The recorded original's Level 1 shows four boosters locked until Lv.7 / Lv.9 / Lv.13 / Lv.17 (freeze, hammer, magnet, UFO; the developer did not implement the magnet); the production policy default is used instead."
},
{
"id": "sandblocks_hammer",
"unlockLevel": 7,
"rewardedPlacementId": "booster_refill_sandblocks_hammer",
"reason": "Module 04 default second unlock (level 7). First targeted booster: every level has visible, unlocked, unfilled boxes at its start, so a valid target exists at its introduction; most useful once a box is walled in."
},
{
"id": "sandblocks_ufo",
"unlockLevel": 12,
"rewardedPlacementId": "booster_refill_sandblocks_ufo",
"reason": "Module 04 default third unlock (level 12). Targeted and strongest (clears a whole colour from the board and the reservoirs), so it comes last, when boards carry several boxes per colour and layered reservoirs."
}
]
}Hosting, native-device tests and live-service verification are separately recorded in the delivery handoff. A local build is not proof of a hosted release.
Fonts
Unity-provided defaults only: TextMesh Pro default font for TMP text and LegacyRuntime.ttf for legacy Unity UI. Official TMP Essentials must be installed. Do not add custom font files or atlases. Any historical custom-font references above describe an older revision; they are not current dependencies.
Demo and publishing configuration
Current source verified on 2026-10-09. The Android download is a development demo with debug signing; WebGL is a LocalQA showcase. Ads are included as LiveOps provider adapters and test/local configuration; vendor SDKs and production credentials are not bundled in the buyer package. Native device and live store certification remain pending.
For product help, contact SatisVizion at satisvizion@gmail.com
See Third-Party Notices.txt in the package for the verified dependency and license inventory.
Managed campaign save guard
The editor save guard ignores JSON formatting whitespace outside string literals, including CRLF/LF and pretty-print layout. Keys, values, array order and characters inside strings remain protected: reconcile actual external edits before saving. This editor-only correction preserves all current runtime level bytes and gameplay rules.
Current route validation
All 500 current runtime and authoring winning certificates passed. A separate conservative permanent-wall reachability guard reports 94 existing warnings; these do not prove those levels impossible or establish exhaustive safety for every possible player order. New generator candidates must pass that guard plus exact winning and timer replay. Human difficulty balance remains unmeasured.
IL2CPP procedural primitives
The packaged Game/link.xml preserves the mesh and collider components required by procedural booster primitives. This fixes an engine-stripping error observed in the first WebGL demo. Android and WebGL were rebuilt with the preservation file; gameplay rules and the 500 current levels remain unchanged.