Overview
Beads Out is a portrait bead-sorting puzzle with 500 levels. A conveyor belt of beads (80 rows of six) turns around a loop past a spout. Tap a box in the tray: it flies to the lowest free shelf slot, and every belt row of its colour that passes the spout pours into it. A full box flies away and frees its slot. Side feeder arms drop their queued rows into empty belt rows. Fill every box to win. If the shelf is full and nothing pours or enters the belt for a whole lap, the level offers one recovery (the newest box returns to the tray); the next stall loses. Level 1 (the tutorial) and level 200 are the two recorded boards of the original game; the other 498 are generated from a saved seed.
Getting Started
- Create or open a Unity 6000.0.62f1 project that uses the Universal Render Pipeline, the Input System package (
activeInputHandler= Input System or Both), Unity UI and the Test Framework. Import TextMesh Pro Essential Resources when prompted. - Import this package. Two roots appear:
Assets/Game(game, scene, levels, tools) andAssets/HyperCasualLiveOpsKit(menu, economy, LiveOps, boosters). - Assign a URP pipeline asset in Graphics/Quality settings (the tested PC/Mobile assets are in
Assets/Game/ProjectRenderSettings) and set Player → Color Space to Linear. - Add
Assets/HyperCasualLiveOpsKit/StarterMenu/Scenes/HLK_MainMenu.unityfirst andAssets/Game/Scenes/Game.unitysecond to the build list, open the menu scene and press Play. Choose a level or press Play Next Level. - Open Tools → Beads Out → Documentation for this guide, Level Editor / Auto Level Generator for the tools.
Folder Structure
| Folder | Contents |
|---|---|
Game/Scripts/Core | Pure C# rules: Sim (100 Hz simulation), LevelData (JSON contract), Witness (tap sequences, replay, solver, players, losing routes), MiniJson. |
Game/Scripts/Game, Game/Scripts/UI, Game/Scripts/Models | Presentation: viewport/camera fit, track geometry, board, beads and box views, lock, HUD, models, the level catalog. |
Game/Integration | The HLK bridge (level selection, pointer gating, runtime fit between the kit HUD and booster shelf, single reward settlement, analytics, audio cues) and the booster adapter. |
Game/Resources/Levels | Level_1.json … Level_500.json plus CampaignAuthoring.json (editor metadata, never a level). |
Game/Resources/LevelSources | The two recorded levels, unchanged, used as authored sources for slots 1 and 200 and as the geometry templates of the two tracks. |
Game/Resources/NativeModels, Materials, Shaders, Art | Track rings, feeder arm, spout, bead, box and lid models; materials; the glossy bead shader; coin, hand and key images. |
Game/Art/Boosters | Centre icon and tutorial illustration of each of the three boosters, bound by booster id in the power-up definitions. |
Game/LevelTools, Game/ProductionLevelTools | Beads Out editor/generator adapter and the shared level-tool framework (editor only). |
Game/Scenes/Game.unity | The gameplay scene (GameRoot, EventSystem, kit gameplay overlay). |
Gameplay
Two tracks come from the recordings: the tall Level 1 track (no feeders) and the wide Level 200 track with two feeder arms. The loop itself is level data: a level either keeps the recorded ring or stores its own closed path, one of 13 silhouettes (rounded square, round, broad low loop, hourglass, tilted pear, rounded triangle, domed/flat, kidney, leaning, rounded diamond, D, heart, S-bend). The same belt rules apply on every loop - 80 rows of six beads, one spout under the bottom, feeder arms joining on their own side - and the loop is drawn with the same procedural channel, rims and chevrons. Trays are stepped stacks of one to five box rows on one shared column grid: stacks that narrow downwards are centred (the two recorded trays), other row profiles are left-aligned. A chain (padlock) covers the bottom row of a tray, or its bottom two rows from four-row trays, and opens 1.25 s after its key box is sent. Losing opportunities come from feeder-only colours: a colour that starts only in a feeder arrives after other colours empty belt rows, so parking it early fills the shelf. Tutorials point the kit's shared tutorial hand at the guided box, with a one-line instruction in a capsule above the board (level 1 boxes, level 8 side belts, level 46 key). Pause, settings, results, rewards and the booster shelf are the kit's; win results appear after the game's own completion celebration.
Scripts Reference
| Script | Role |
|---|---|
Sim | Taps, shelf slots, belt rotation, pours, feeders, lock, boosters (AddSlot, Move any, FillBlock), stall recovery and the loss, win/celebration phases, published snapshot. |
LevelData | Parses and validates a level (bead conservation per colour, ring/spout/junction rows, optional loop path, track, tutorial and key references). |
RingCurve | The loop centreline of a level (recorded ring or saved control points through a closed Catmull-Rom), with the belt rows at equal arc steps and the spout row on the loop bottom; shared by the runtime track, the editor and the validator. |
Witness | Parses/formats step:boxId certificates, replays them through the real Sim, the greedy solver with bounded branch search, seeded random/careless players and the fixed losing route. |
GameController | Builds a level, routes pointer presses into the Sim, steps it on the fixed clock, drives the views; host hooks for the kit shell. |
Viewport | Maps the portrait column to screen and ground; fits the level between the host HUD and controls (HostPlayArea). |
BeadsHlkBridge, BeadsPowerUpAdapter | Kit integration: level selection, settlement, analytics, audio; booster handlers, arming and availability. |
BeadsBoards, BeadsProgression, BeadsLevelRules, BeadsCampaignRules, GameAdapter | Editor: board builder, chapter plan and schedule, keys and checks, campaign rules, the shared-tool adapter. |
BeadsPaths, BeadsPathCatalog | Editor: the loop catalog (control points per silhouette and track), the loop schedule, feeder re-attachment and loop checks (bend radius, length, fit, spout, arm clearance). |
Level Editor
Tools → Beads Out → Level Editor lists the campaign with Undo, duplicate, delete and reorder, a spatial canvas and an exact JSON view. The canvas draws the loop on its real centreline with flow arrows, every starting belt row in its colour, the feeder queues and their junctions, the shelf slots and the tray boxes with the key icon and chain. Tools: paint a box, paint five belt rows, move a box into or out of the chained zone, choose the key box; pick the tray formation, the shelf size (3-5 slots), the box capacity (20 or 10 rows) and the loop (a catalog preset, copied into this level only). The Loop points tool drags the loop's control points, double-click on the loop inserts one, right-click removes one, shift-click moves that side's feeder junction; the arms re-attach after every edit and a warning names any loop rule that fails. Edits clear the witness; saving re-solves, validates bead conservation, overlaps and the campaign rules, and publishes through staging. Play opens the saved level through the normal menu flow.
Automatic Level Generator
Tools → Beads Out → Auto Level Generator uses the saved request (count, seed, attempts, minimum formations, streak limit, append/replace). Generation is deterministic: the same request yields the same campaign. Each candidate is built from its chapter blueprint, solved, replayed through the Sim and checked for duplicates, formation streaks and chapter rules; the loop silhouette follows its own seeded schedule (recorded ring at levels 1, 8 and 200, the reference shapes at levels 27, 42, 45, 48 and 78, otherwise no silhouette again within two levels); bounded retries never weaken constraints, and a failure leaves the published JSON unchanged. Append mode keeps every existing level and adds new ones to the target count.
Boosters
| Booster | Effect | Unlock / free charges |
|---|---|---|
| Extra Slot | Adds one shelf slot for this level (up to six). | Level 2 · 2 once |
| Move Any | Targeted: tap any tray box, even a chained one, to send it; with a full shelf the newest box returns to the tray. Tap the booster again to cancel. | Level 7 · 2 once |
| Fill | Pulls matching beads from the belt and feeders into the first unfinished shelf box. | Level 12 · 2 once |
The effects are the V2 developer's; the kit supplies inventory, first-use tutorials, arming, audio and DEV unlock/refill/tutorial controls.
Progression and refills. A booster unlocks permanently when a real win makes its level reachable (completing level 1 unlocks Extra Slot for level 2) and stays usable on earlier replays; on that first unlock it grants two free charges, once per booster and never per level. Each successful effect costs one charge; a refused, cancelled or invalid use costs nothing. At zero the button shows a gray icon with a white 0 and opens the kit's GET ANOTHER BOOST popup: BUY +1 for 100 coins plus 25 per 10 levels of real progress (no replay discount), or WATCH AD +1 on the booster's rewarded placement (booster_refill_<id>). A refill adds one charge and closes the popup without firing the booster; skipped, failed or unavailable ads grant nothing, and every purchase is journaled so an interrupted transaction is settled exactly once on the next launch. DEV level jumps and DEV refills never grant charges or record progress. Inventory is saved per profile (HLK.beads-out.<profile>.Booster.*); older saved counts are migrated, not reset.
Level Variation
| Levels | Chapter | What changes |
|---|---|---|
| 1 | Tutorial | Recorded Level 1. |
| 2-7 | Tap and fill | Tall track, new tray shapes, everything on the belt. |
| 8-20 | Side feeders | Wide track; feeders refill emptied rows (level 8 guided). |
| 21-45 | Plan the belt | Feeder-only colours; parking them early fills the shelf. |
| 46-70 | Key and chain | Chained bottom rows (level 46 guided key tap). |
| 71-120 | Mixed belt | Shorter colour runs, repeated colours. |
| 121-190 | Three slots | Three-slot shelves (level 121 introduction). |
| 191-280 | Level 200 scale | Recorded Level 200 size (authored level 200). |
| 281-380 | Small boxes | 10-row boxes double the tray (level 281 introduction). |
| 381-500 | Master | Everything combined. |
Every level ending in 5 from 25 is a lighter relief level. From level 21 the box and colour counts rise toward those seen in later levels of the original game, up to 20 boxes and 13 colours in the Master chapter, with belt colour runs of 5-10 rows. The shipped campaign has 499 distinct tray/track/chain/feeder/loop formations (378 tray row profiles) and never repeats a formation on consecutive levels (the generator allows at most two in a row). The loop varies separately: all 13 silhouettes appear in every chapter from level 21, a silhouette never returns within two levels, and every 20-level window shows at least 11 of them.
Customization Guide
- Difficulty: edit
BeadsProgression.Chapters(boxes, colours, feeder-only share, chain chance, shelf and capacity mixes, run lengths) and regenerate with a new seed, or hand-edit levels in the editor. - Colours:
BeadsBoards.Colours/Hexlist the thirteen recorded bead colours; look-alike families are kept apart early. - Tray shapes: a tray is a row profile (
TrayShape, boxes per row, e.g.5-5-4-2).BeadsBoards.Shapesenumerates the profiles each track allows from its measured grid (TallGrid: up to 2 rows / 8 boxes,WideGrid: up to 5 rows / 20 boxes);ChainRowssets the chained rows. New profiles raise formation variety automatically. - Loops: reshape one level with the Loop points tool, or add a silhouette to
BeadsPathCatalog.Families(40 column u,v control points per track);BeadsPaths.Checkaccepts it when it bends no tighter than the channel, keeps 94-112% of the recorded loop length (same rows and bead size), stays inside the recorded track band and leaves room for both feeder arms.BeadsPaths.Scheduleplaces the silhouettes in the campaign. - Boosters: unlock levels, the one-time grant, refill amount, prices and rewarded placements live in
Game/Resources/HLK/BoosterProgression.json(the file the player loads; it sets each definition's unlock level at start-up and is validated against the power-up catalog). Names, icons and tutorials are in the definition assets (Game/Integration/PowerUps); effects inSim.AddSlot,Sim.TapBox(Move any) andSim.FillBlock. The kit'sPowerUps/BOOSTER-PROGRESSION.mdandBOOSTER-REFILL-UI.mddescribe the shared policy and popup. - Rewards, ads, LiveOps: see the HyperCasualLiveOpsKit guide.
- DEV panel: the orange DEV button is a development tool; hide it for store builds with
StarterGameplayDevPanel.IsAvailable = false.
Level Format
Each Level_N.json holds the track data (column size, ring rectangle, spout, feeder arm paths and junction rows), the optional loop ring.path (id = catalog silhouette, a trailing * marks a hand-edited copy; points = closed control points as column fractions; absent = the recorded ring), the palette, ring.rows0 (80 belt rows, clockwise from the top; null = empty), each feeder's rows0 queue (first row nearest the junction), box.capacityRows, the shelf slot rectangles, the tray (plate, cut-out with one rectangle per row block, boxes with grid cell, rectangle, colour, locked, key), the optional lock, the tutorial (guided box ids, caption, hint), HUD/result data, track (tall or wide), plus index and the witness (step:boxId taps on the 100 Hz clock). Rectangles are fractions of the portrait column (x right, y down). Current level 4 (complete):
{
"levelId": "Level_4",
"levelNumber": 4,
"title": "Level 4",
"column": {
"width": 474,
"height": 1080,
"sourceFrame": [
1440,
1080
],
"sourceCrop": [
0.3347,
0,
0.6639,
1
],
"fps": 60
},
"palette": {
"background": "#ABC7FB",
"backgroundFooter": "#83ACEE",
"rim": "#425ABD",
"channel": "#A8A8B1",
"slot": "#D5DCF4",
"trayPlate": "#8FA4DE",
"yellow": "#FFE322",
"green": "#3BF218",
"red": "#FF2141",
"blue": "#078DFF"
},
"ring": {
"rows": 80,
"spoutRow": 40,
"beadsPerRow": 6,
"rowPitchPx": 11.5,
"foreshortening": 0.82,
"rows0": [
"blue",
"blue",
"blue",
"blue",
"blue",
"blue",
"blue",
"blue",
"blue",
"blue",
null,
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
null,
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
null,
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
null,
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
null,
null,
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
null,
null,
"red",
"red",
"red",
"red",
"red",
"red",
"red",
"red",
"red",
"red",
null,
null
],
"screen": {
"cx": 0.5011,
"cy": 0.3907,
"hw": 0.2089,
"hh": 0.1245,
"rx": 0.1646,
"ry": 0.0593,
"outerRimPx": 8,
"channelPx": 50
},
"spoutScreen": {
"x": 0.4557,
"y": 0.5417,
"w": 0.0928,
"h": 0.0398
}
},
"feeders": [],
"conveyor": {
"slowRowsPerSec": 7.5,
"fastMultiplier": 2,
"speedUpDelayAfterTutorial": 0.6,
"speedUpRamp": 0.45
},
"box": {
"capacityRows": 10,
"flyToShelf": 0.2,
"armDelay": 0.2,
"beadFlight": 0.25,
"fullGlow": 0.3,
"slotFreeAfterFull": 0.3,
"flyAway": 0.6,
"goneAfterFull": 0.9,
"percentStep": 5
},
"shelf": {
"slots": [
{
"x": 0.1709,
"y": 0.613,
"w": 0.154,
"h": 0.0565
},
{
"x": 0.3418,
"y": 0.613,
"w": 0.154,
"h": 0.0565
},
{
"x": 0.5084,
"y": 0.613,
"w": 0.154,
"h": 0.0565
},
{
"x": 0.6793,
"y": 0.613,
"w": 0.154,
"h": 0.0565
}
]
},
"tray": {
"plate": [
{
"x": 0,
"y": 0.7037,
"w": 1,
"h": 0.25
}
],
"cutout": [
{
"x": 0.0669,
"y": 0.7037,
"w": 0.8662,
"h": 0.0953
},
{
"x": 0.1389,
"y": 0.799,
"w": 0.7222,
"h": 0.0834
}
],
"boxes": [
{
"id": "box-yellow-1",
"colour": "yellow",
"cell": "r1c1",
"rect": {
"x": 0.1329,
"y": 0.7083,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-yellow-2",
"colour": "yellow",
"cell": "r1c2",
"rect": {
"x": 0.3249,
"y": 0.7083,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-green-1",
"colour": "green",
"cell": "r1c3",
"rect": {
"x": 0.5169,
"y": 0.7083,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-yellow-3",
"colour": "yellow",
"cell": "r1c4",
"rect": {
"x": 0.7089,
"y": 0.7083,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-green-2",
"colour": "green",
"cell": "r2c1",
"rect": {
"x": 0.2289,
"y": 0.8009,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-red-1",
"colour": "red",
"cell": "r2c2",
"rect": {
"x": 0.4209,
"y": 0.8009,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-blue-1",
"colour": "blue",
"cell": "r2c3",
"rect": {
"x": 0.6129,
"y": 0.8009,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
}
]
},
"lock": null,
"tutorial": {
"caption": "",
"captionRect": {
"x": 0.1266,
"y": 0.463,
"w": 0.7468,
"h": 0.0787
},
"captionUntilStep": 0,
"steps": [],
"handTapPeriod": 0.5,
"hint": ""
},
"hud": {
"levelPill": {
"x": 0.3966,
"y": 0.0602,
"w": 0.211,
"h": 0.0398
},
"coinPill": {
"x": 0.7722,
"y": 0.0602,
"w": 0.2278,
"h": 0.0444
},
"gear": {
"x": 0.0464,
"y": 0.0602,
"w": 0.0928,
"h": 0.0398
},
"coins": 500,
"boosters": [
{
"x": 0.2743,
"locked": true,
"label": "Level 6"
},
{
"x": 0.5173,
"locked": true,
"label": "Level 8"
},
{
"x": 0.7512,
"locked": true,
"label": "Level 11"
}
],
"boosterY": 0.94
},
"result": {
"title": "Congrats",
"nextReward": 25,
"newFeatureFrom": 0,
"newFeatureTo": 0,
"adButton": null,
"awesomeBanner": false,
"confettiFromCompletion": 2,
"celebrationSparkle": 1.1,
"dimAt": 1.2,
"titleAt": 1.3,
"buttonAt": 1.8,
"nextRect": {
"x": 0.3165,
"y": 0.6157,
"w": 0.3692,
"h": 0.0509
}
},
"evidence": {
"originTimestamp": 0,
"durationMs": 0,
"generated": true
},
"track": "tall",
"provenance": {
"chapter": "Tap and fill",
"formation": "tall|4-3|open|f0",
"relief": false,
"seed": 1756478264
},
"index": 4,
"witness": "0:box-yellow-1;1:box-yellow-2;2:box-green-1;3:box-yellow-3;183:box-green-2;265:box-red-1;498:box-blue-1"
}Support
Questions and bug reports: satisvizion@gmail.com. Please include the Unity version, the level number and the editor console output.
Licences and Notices
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/Beads Out/Documentation, Tools/Beads Out/Level Editor, Tools/Beads Out/Auto Level Generator.
Current complete level example
Assets/Game/Resources/Levels/Level_4.json
{
"levelId": "Level_4",
"levelNumber": 4,
"title": "Level 4",
"column": {
"width": 474,
"height": 1080,
"sourceFrame": [
1440,
1080
],
"sourceCrop": [
0.3347,
0,
0.6639,
1
],
"fps": 60
},
"palette": {
"background": "#ABC7FB",
"backgroundFooter": "#83ACEE",
"rim": "#425ABD",
"channel": "#A8A8B1",
"slot": "#D5DCF4",
"trayPlate": "#8FA4DE",
"yellow": "#FFE322",
"green": "#3BF218",
"red": "#FF2141",
"blue": "#078DFF"
},
"ring": {
"rows": 80,
"spoutRow": 40,
"beadsPerRow": 6,
"rowPitchPx": 11.5,
"foreshortening": 0.82,
"rows0": [
"blue",
"blue",
"blue",
"blue",
"blue",
"blue",
"blue",
"blue",
"blue",
"blue",
null,
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
null,
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
null,
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
null,
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
null,
null,
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow",
null,
null,
"red",
"red",
"red",
"red",
"red",
"red",
"red",
"red",
"red",
"red",
null,
null
],
"screen": {
"cx": 0.5011,
"cy": 0.3907,
"hw": 0.2089,
"hh": 0.1245,
"rx": 0.1646,
"ry": 0.0593,
"outerRimPx": 8,
"channelPx": 50
},
"spoutScreen": {
"x": 0.4557,
"y": 0.5417,
"w": 0.0928,
"h": 0.0398
}
},
"feeders": [],
"conveyor": {
"slowRowsPerSec": 7.5,
"fastMultiplier": 2,
"speedUpDelayAfterTutorial": 0.6,
"speedUpRamp": 0.45
},
"box": {
"capacityRows": 10,
"flyToShelf": 0.2,
"armDelay": 0.2,
"beadFlight": 0.25,
"fullGlow": 0.3,
"slotFreeAfterFull": 0.3,
"flyAway": 0.6,
"goneAfterFull": 0.9,
"percentStep": 5
},
"shelf": {
"slots": [
{
"x": 0.1709,
"y": 0.613,
"w": 0.154,
"h": 0.0565
},
{
"x": 0.3418,
"y": 0.613,
"w": 0.154,
"h": 0.0565
},
{
"x": 0.5084,
"y": 0.613,
"w": 0.154,
"h": 0.0565
},
{
"x": 0.6793,
"y": 0.613,
"w": 0.154,
"h": 0.0565
}
]
},
"tray": {
"plate": [
{
"x": 0,
"y": 0.7037,
"w": 1,
"h": 0.25
}
],
"cutout": [
{
"x": 0.0669,
"y": 0.7037,
"w": 0.8662,
"h": 0.0953
},
{
"x": 0.1389,
"y": 0.799,
"w": 0.7222,
"h": 0.0834
}
],
"boxes": [
{
"id": "box-yellow-1",
"colour": "yellow",
"cell": "r1c1",
"rect": {
"x": 0.1329,
"y": 0.7083,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-yellow-2",
"colour": "yellow",
"cell": "r1c2",
"rect": {
"x": 0.3249,
"y": 0.7083,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-green-1",
"colour": "green",
"cell": "r1c3",
"rect": {
"x": 0.5169,
"y": 0.7083,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-yellow-3",
"colour": "yellow",
"cell": "r1c4",
"rect": {
"x": 0.7089,
"y": 0.7083,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-green-2",
"colour": "green",
"cell": "r2c1",
"rect": {
"x": 0.2289,
"y": 0.8009,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-red-1",
"colour": "red",
"cell": "r2c2",
"rect": {
"x": 0.4209,
"y": 0.8009,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
},
{
"id": "box-blue-1",
"colour": "blue",
"cell": "r2c3",
"rect": {
"x": 0.6129,
"y": 0.8009,
"w": 0.1582,
"h": 0.0648
},
"locked": false,
"key": false
}
]
},
"lock": null,
"tutorial": {
"caption": "",
"captionRect": {
"x": 0.1266,
"y": 0.463,
"w": 0.7468,
"h": 0.0787
},
"captionUntilStep": 0,
"steps": [],
"handTapPeriod": 0.5,
"hint": ""
},
"hud": {
"levelPill": {
"x": 0.3966,
"y": 0.0602,
"w": 0.211,
"h": 0.0398
},
"coinPill": {
"x": 0.7722,
"y": 0.0602,
"w": 0.2278,
"h": 0.0444
},
"gear": {
"x": 0.0464,
"y": 0.0602,
"w": 0.0928,
"h": 0.0398
},
"coins": 500,
"boosters": [
{
"x": 0.2743,
"locked": true,
"label": "Level 6"
},
{
"x": 0.5173,
"locked": true,
"label": "Level 8"
},
{
"x": 0.7512,
"locked": true,
"label": "Level 11"
}
],
"boosterY": 0.94
},
"result": {
"title": "Congrats",
"nextReward": 25,
"newFeatureFrom": 0,
"newFeatureTo": 0,
"adButton": null,
"awesomeBanner": false,
"confettiFromCompletion": 2,
"celebrationSparkle": 1.1,
"dimAt": 1.2,
"titleAt": 1.3,
"buttonAt": 1.8,
"nextRect": {
"x": 0.3165,
"y": 0.6157,
"w": 0.3692,
"h": 0.0509
}
},
"evidence": {
"originTimestamp": 0,
"durationMs": 0,
"generated": true
},
"track": "tall",
"provenance": {
"chapter": "Tap and fill",
"formation": "tall|4-3|open|f0",
"relief": false,
"seed": 1756478264
},
"index": 4,
"witness": "0:box-yellow-1;1:box-yellow-2;2:box-green-1;3:box-yellow-3;183:box-green-2;265:box-red-1;498:box-blue-1"
}Level fields
| Field | JSON type |
|---|---|
| levelId | str |
| levelNumber | int |
| title | str |
| column | dict |
| palette | dict |
| ring | dict |
| feeders | list |
| conveyor | dict |
| box | dict |
| shelf | dict |
| tray | dict |
| lock | NoneType |
| tutorial | dict |
| hud | dict |
| result | dict |
| evidence | dict |
| track | str |
| provenance | dict |
| index | int |
| witness | str |
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": "beads-out",
"defaultProfileId": "default",
"initialGrant": 2,
"refillAmount": 1,
"baseCoinCost": 100,
"coinCostStep": 25,
"levelsPerPriceStep": 10,
"rewardedTimeoutSeconds": 90,
"boosters": [
{
"id": "beads_extra_slot",
"unlockLevel": 2,
"rewardedPlacementId": "booster_refill_beads_extra_slot",
"reason": "Module 04 default first unlock (level 2). Simplest idea: one more shelf slot while boxes wait for their colour; useful on every board."
},
{
"id": "beads_move_any",
"unlockLevel": 7,
"rewardedPlacementId": "booster_refill_beads_move_any",
"reason": "Module 04 default second unlock (level 7), just before side feeders (level 8): sends any box to the shelf, useful once colours arrive from the arms."
},
{
"id": "beads_fill",
"unlockLevel": 12,
"rewardedPlacementId": "booster_refill_beads_fill",
"reason": "Module 04 default third unlock (level 12): fills a box directly, most valuable after feeder-only colours start (level 9+). Teaching order kept from the recorded badges (extra slot, move any, fill = 6/8/11)."
}
]
}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.