A Hexagonal Slide-to-Hole Puzzle Game — Unity Template
Version 1.0 | Unity 6+ | URP
This asset is designed as a template and starting point for your own game development. It provides the core systems, architecture, and tools needed to build a hexagonal slide-puzzle game. You are expected to customize, extend, and modify this template to create your unique game. This is not a complete, ready-to-publish game — it's a foundation for developers to build upon.
Hexa Away Puzzle 3D is a hexagonal slide-to-hole puzzle game where players tap colored hex stacks to launch them along their arrow direction. If the path is clear, the stack flies off the board; if another stack is in the way, the tap bumps and still costs a move. Clear every stack within the level's move budget to win. The game features a procedural hex mesh, a built-in level editor, an automatic level generator with a built-in solvability validator, and a booster system.
Intuitive one-tap controls — tap any reachable hex stack to launch it along its arrow direction. Stacks bump, rotate, or clear depending on what's ahead.
Full Unity Editor window for designing hex levels with a visual grid painter — place grounds, holes, and colored stacks on a double-offset hex grid with color and direction pickers.
Batch-generate hundreds of playable hex levels with configurable difficulty curves, level width and height (up to 24 hex-rows tall), color counts, island spread, and per-level booster budgets.
Three in-game boosters — Bomb (clears a stack plus its 6 neighbours), +Moves (adds 5 moves to the run), and Hint (pulse-highlights a launchable stack) — with first-use tutorial popups and per-level unlocks.
Ships with 500 pre-generated levels on a progressive difficulty curve, every one validated solvable by the built-in greedy solver before being written to disk. Generate more at any time with the auto generator.
Edit > Project Settings > Graphics)Assets/Hexa Away Puzzle 3D/Scenes/GameNew.unityOnce in Play mode, tap any hex stack whose arrow direction is unblocked — it flies off the board in that direction and you score a clearance. Tap a blocked stack and it bumps, consuming a move but not clearing. Clear every stack within the move budget to win and the next level loads automatically. A wrong tap still costs a move, so the player can genuinely lose.
Each level is a hex-grid of colored stacks and holes laid out on a flat-topped, double-offset hex coordinate system. Every stack points in one of six hex directions and launches along that arrow when tapped.
All stacks use one of six hex directions in flat-topped double-height-offset coordinates. The direction enum value is serialized directly into the JSON level files:
| Enum | Value | Cell Offset (Δcol, Δrow) |
|---|---|---|
Up | 0 | (0, -2) |
Down | 1 | (0, +2) |
UpperLeft | 2 | (-1, -1) |
UpperRight | 3 | (+1, -1) |
LowerLeft | 4 | (-1, +1) |
LowerRight | 5 | (+1, +1) |
The base palette ships with seven configurable colours. The auto generator picks a 3–7-colour subset per level based on difficulty.
| Color Key | Color | Reference Hex |
|---|---|---|
red | Red | #FF4757 |
orange | Orange | #FFA502 |
green | Green | #7BED9F |
gray | Gray | #A4B0BE |
blue | Blue | #48DBFB |
purple | Purple | #BC8CFF |
black | Black | #2D2D2D |
The palette key is the lowercase string written into the JSON. Materials in Art/Materials/ are matched by file name (red.mat, orange.mat, …).
Each stack has three animation states: idle (static, with the direction arrow visible on top), launch (tumble + slide along the hex axis when the path is clear), and bump (small kick-back when the path is blocked). Cleared stacks play a tile-by-tile fall-off cascade. The Bomb booster adds an explosion burst with an outward shockwave on the targeted stack and its 6 neighbours.
Runtime scripts use the HypercasualGameEngine namespace. Editor scripts use the HypercasualGameEngine.EditorTools namespace. The engine namespace is shared across every game in the bundle — do not change it, or save files written by other games will fail to load.
| Script | Description |
|---|---|
HexaAwayGameManager |
Top-level orchestrator. Decorated [DefaultExecutionOrder(-100)] so it runs before every other script. Tracks the game state enum (Playing / Won / Lost), creates missing scene singletons (EventSystem, SoundManager, BoosterManager) via FindFirstObjectByType, handles arrow-key level navigation and the U-key booster debug shortcut, and is the single call site for TriggerWin / TriggerLose. |
HexLevelManager |
Gameplay core. Reads the current LevelData from LevelManager.GetCurrentLevel() and spawns one HexStack per LevelStackData entry. Handles tap-to-launch raycasts, pathfinds along arrow directions, counts moves, and runs the bomb / hint power-ups. Never falls back to an Inspector-assigned demo level. |
HexStack |
Container for a visual stack of hex tiles at a grid coordinate. Holds the direction, the tile list, and the logic to mark the new top tile after each removal. Setup() takes the coords, direction, top + side material pair, stack size, and hex radius. |
HexTile |
Individual hex disc inside a stack. Owns the top + side material assignment, the direction arrow renderer (top tile only), and the bomb-explode coroutine. |
HexTileAnimator |
All tile-level animation coroutines: tumble, slide along a hex axis, fly-off, and the staggered top-to-bottom fall-off cascade when a stack is cleared. |
HexCoordinates |
Double-offset hex math. Provides ToWorldPosition(hexRadius) on the XZ plane, the six neighbour offsets, and the HexDirection enum + its HexDirectionHelper with GetOffset, GetWorldDirection, and GetTumbleAxis. |
HexMeshGenerator |
Procedurally builds the flat-topped hex mesh with separate top and side sub-meshes so each can take its own material. |
LevelManager |
Static class that loads Level_N.json files from Resources/Levels/ at runtime via Resources.Load<TextAsset>("Levels/Level_" + i) in a strict-sequential loop, tracks the current level index via the HexaAwayPuzzle3D_CurrentLevel PlayerPrefs key, and provides editor-only save / delete APIs that read from the absolute path under Assets/Hexa Away Puzzle 3D/Resources/Levels/. |
BoosterManager |
Three-booster state machine. Owns the booster counts (single source of truth — gameplay scripts never store counts of their own), level-gated unlock (booster N unlocks at level N−1), first-use tutorial popup keyed in PlayerPrefs, and the four-state HUD button UI (Locked / Usable / Depleted / Active). Exposes OnBombActivated / OnMovesBoosterUsed / OnHintActivated for per-game wiring. |
SoundManager |
Singleton audio facade. Single AudioSource, single masterVolume slider. One Play<Event>() method per game event — PlayTap(), PlayBlocked(), PlayLevelClear(), PlayLevelFail(), PlayBoosterActivate(). No background music by design. |
LevelData |
Serializable POCO: totalMoves, bombCount, movesBoosterCount, hintBoosterCount, stackSize, plus lists of LevelStackData (col, row, colorName, direction) and LevelHoleData (col, row). |
LoseWinPanelManager |
Win / lose overlay prefab controller. LoadNextLevel calls LevelManager.AdvanceLevel() before reloading the scene so progression actually advances (the template placeholder-bug is patched). ShowWin() writes "LEVEL N" into winLevelText before activating LevelClearedPanel; ShowLose() intentionally does NOT populate a level-number field (GameOverPanel has no such TMP by design). Self-wires at Start() via AutoWireReferences() — searches first for direct children WinPanel / LosePanel, then scene-wide for LevelClearedPanel / GameOverPanel, and recursively for ButtonRetry / ButtonContinue / CurrentLevelText. Also exposes an Auto-Wire References context menu item for in-editor preview. Does NOT modify LocalScale on show — respects whatever design-time scale the panels have in the scene. |
GameHUD |
Binds the existing HUD prefab's CurrentLevelText and moves counter to game state. Lives on the GameHUD_Panel prefab root — does not create its own Canvas at runtime (single-canvas invariant: the template canvas is the only canvas in the scene). |
| Script | Description |
|---|---|
DeveloperModeButton |
Toggles a developer settings panel on click. Auto-finds a child literally named DeveloperSettingsPanel if no reference is assigned in the inspector. |
DeveloperSettingsController |
Developer panel with buttons for level navigation (next, previous, reload, trigger win / lose), booster debugging (unlock all, refill all, reset popups), and ad testing (show / hide banner, show / request interstitial, show / request rewarded). Shift+combo hotkeys live here; plain-arrow / plain-U handlers live on HexaAwayGameManager (so they fire even when the dev panel GameObject is inactive). |
CameraSwitcher |
Multi-camera helper from the engine bundle. Unused in the single-scene build but kept for reference if you later add an in-app launcher across multiple games. |
| Script | Description |
|---|---|
LevelEditorWindow |
Unity Editor window (Tools > Hexa Away Puzzle 3D > Level Editor) for visually designing hex levels. Two-pane layout: left panel with level list and add / duplicate / reorder / delete / save-all / reload actions; right panel with hex-grid painter, paint-mode toolbar, and per-level fields (move budget, booster counts, stack size, palette). |
LevelGenerator |
Auto level generator core. Owns the four-stage solvability loop (preferred → solvable-only → difficulty-eased → minimal fallback), the difficulty-curve interpolation, the polar island seeding, the connected-land BFS growth, the hole-vs-stack partitioning with interior-bias, and the greedy fire-anything-launchable solver used to validate every candidate before it's written to disk. |
LevelGeneratorWindow |
Unity Editor window (Tools > Hexa Away Puzzle 3D > Auto Level Generator) that exposes the LevelGenSettings struct as a min/max pair UI and runs the generator with a cancellable progress bar. |
HexaAwayPuzzle3DWelcomePopup |
Welcome popup that auto-opens once per editor session via [InitializeOnLoadMethod]. Two CTA buttons (leave a review on the Asset Store, get the HyperCasual Game Engine bundle) plus a "Do not show this popup again" checkbox. Permanently dismissable via EditorPrefs. Not exposed in the menu. |
In the Unity menu bar, go to Tools > Hexa Away Puzzle 3D > Level Editor. This opens a dedicated Editor window — no need to enter Play mode.
Level_N.json atomically (green button); Reload from Disk discards in-memory changes and re-reads the folder (with confirmation)| Mode | Left Click |
|---|---|
| Ground | Place a base ground tile at the clicked cell. Stacks need a ground beneath them. |
| Hole | Mark the clicked cell as a hole — a gap in the land that interrupts a launch path. |
| Stack | Place a colored stack at the clicked cell using the currently-selected colour and direction. Click again with a different colour / direction to overwrite. |
| Erase | Remove whatever ground / hole / stack is at the clicked cell. |
All levels are stored as individual JSON files in Assets/Hexa Away Puzzle 3D/Resources/Levels/ with the naming convention Level_1.json, Level_2.json, …, Level_N.json. They are loaded at runtime via a strict-sequential Resources.Load<TextAsset>("Levels/Level_" + i) loop — a gap in the numbering will truncate the playable set.
The Automatic Level Generator is an Editor tool that batch-generates playable hex puzzles. Every candidate is run through the built-in greedy solver before being written to disk — nothing unsolvable is ever saved, even as a last-resort fallback.
In the Unity menu bar, go to Tools > Hexa Away Puzzle 3D > Auto Level Generator. This opens a settings window where you can configure all parameters as min/max pairs before generating. The left value is the difficulty-0 (easy) end; the right value is the difficulty-1 (hard) end.
| Setting | Description |
|---|---|
| Levels To Generate | How many new level files to create. New levels are appended after existing ones (the generator never overwrites). Default: 500. |
| Spread Radius (Min & Max) | Polar distance that island seeds spawn from the grid centre. Larger spread = wider multi-island layouts. Default: 3 → 8. |
| Land Count (islands) | Number of disconnected land pieces per level. Typically 1 at easy, 2–3 at hard. Default: 1 → 3. |
| Stacks / Level | Total stack count per level — the dominant difficulty driver. Default: 6 → 32. |
| Holes / Level | Number of hole cells drilled into the land. Biased toward interior cells so harder levels sometimes get donut-shaped islands. Default: 1 → 8. |
| Stack Size | Visual height of each stack in tiles. Cosmetic only — does not affect gameplay. Default: 3 → 6. |
| Error Margin | Extra moves above the strict minimum, expressed as a multiplier. moves = stacks + round(stacks × errorMargin). Easy = 1.00 (lots of room); hard = 0.15 (tight). Note: invalid taps cost a move too, so this is genuine headroom. |
| Colors In Play | Subset of the 7-colour palette used per level. Default: 3 → 7. |
| Bomb / +Moves / Hint Booster Counts | Min / max booster counts per level. Inverted difficulty: more boosters on early levels, fewer on harder ones. |
| Use Fixed Seed | When enabled, runs the generator with a deterministic seed so the same settings always produce the same level set. Useful for reproducible regeneration. |
Resources/Levels/The generator clips every level to a hard 11 hex-columns × 24 hex-rows envelope so the land stays within the camera frustum. Stacks and holes are never placed outside this box even if the requested radius would push them out. The 24-row vertical cap means later levels can stretch up and down on screen far beyond what the early-game examples show.
The generator never overwrites existing level files. It always starts numbering from the next available index. Use the red "Delete ALL Levels" button at the bottom of the window if you want to wipe the folder and start fresh. Every save also goes through the solvability validator — the generator will skip a slot rather than write a broken level.
The game includes three booster abilities that players can activate during gameplay. Each booster has a configurable starting count per level (set in the level JSON data) and a one-time tutorial popup on first use, dismissed permanently after the player closes it.
| Booster | Effect | Activation |
|---|---|---|
| Bomb | Targeting toggle. Tap a stack on the board to clear it plus its six hex neighbours, regardless of arrow direction. Useful when a stack is unreachable through normal launches. | Tap the Bomb button (Booster-Button-1) to enter targeting mode. Tap a stack to fire. Tap the button again to cancel without consuming a use. |
| +Moves | Adds 5 moves to the current level's move budget. Instant — no targeting step. | Tap the +Moves button (Booster-Button-2). Consumes one use immediately and updates the moves counter on the HUD. |
| Hint | Pulse-flashes one stack on the board that can be cleared right now (its arrow path is unblocked). The flash fades after a couple of seconds; pressing again finds another candidate. | Tap the Hint button (Booster-Button-3). Consumes one use immediately. Does nothing if no stack is currently launchable. |
Booster buttons live in the GameHUD_Panel/BottomHolder in the scene UI. Each button has:
Bg) that shows / hides based on availabilityPowerUpCountText) showing remaining uses, or the unlock level if still lockedrgba(134, 191, 255)) when the Bomb is in targeting mode and waiting for a stack clickBooster counts live on BoosterManager, never on the gameplay script. HexLevelManager stores only the active power-up mode (e.g. "Bomb is in targeting mode") and asks BoosterManager.Instance.ConsumeBomb() when the effect actually fires. This avoids drift between the HUD count label and the underlying state — a class of bugs where the HUD says "1 bomb left" but a click silently does nothing.
Press the U key during gameplay to unlock all boosters and refill their usage counts. Press Right Arrow / Left Arrow to jump to the next / previous level. These shortcuts live on HexaAwayGameManager.Update so they fire even when the dev panel GameObject is inactive.
To add a new stack colour:
LevelGenerator.cs and append the colour key to the static Palette array:
Art/Materials/ with the file name matching the new key (e.g. pink.mat) so it's resolved at runtime by name lookup.LevelEditorWindow if you want to paint the new colour by hand.New colours are automatically eligible for the auto generator's per-level subset (Colors In Play max).
The hex layout is controlled by HexLevelManager.cs. Key properties:
hexRadius — Radius of a single hex in world units (drives both spacing and mesh scale). Default: 0.2887.meshScale — Multiplier applied on top of hexRadius to the procedurally-built mesh. Default: 0.575.hexagonMesh — Override mesh. Leave null to use the procedural mesh built by HexMeshGenerator.Stack rendering is handled by the HexStack + HexTile pair:
HexLevelManager).Art/Textures/ to change the look.stackSize in LevelData controls how many tiles are stacked. Cosmetic only — does not affect gameplay.Edit the constants at the top of LevelGenerator.cs:
DifficultyCeilingLevel (default 12) — The level at which the difficulty curve reaches max. Lowering it makes harder levels appear sooner.DifficultyCurveSharpness (default 0.5) — Curve exponent. <1 = concave (fast ramp, then flat); >1 = convex (slow ramp).MaxColSpan / MaxRowSpan (default 11 / 24) — Hard hex-cell envelope. Raise MaxRowSpan for taller levels but verify the camera frustum still fits.New boosters can be added by following the existing pattern in BoosterManager.cs:
int field to LevelData (e.g. shuffleBoosterCount) so it can be configured per level.BoosterManager.HookUpExistingBoosters() following the existing pattern (find the child by literal string match — Booster-Button-N names are load-bearing, do not rename).HexLevelManager if it needs game-state access.UpdateBoosterUI() to handle the new booster's lock / unlock / count display.Each level is a JSON file with the following structure:
Coordinates use double-height hex offset with the centre at (12, 12). Valid cells satisfy parity: (col + row) must be even (or odd, depending on the starting parity of the level — mixing parities will produce gaps in the visible board). The colorName string must match a key in LevelGenerator.Palette and a .mat file in Art/Materials/.
| Issue | Solution |
|---|---|
| No levels load / empty board appears | Ensure JSON level files exist in Assets/Hexa Away Puzzle 3D/Resources/Levels/ with the naming convention Level_1.json, Level_2.json, …. Use the Auto Level Generator to create levels if the folder is empty. The loader is strictly sequential — a missing index truncates the playable set. |
| Pink / magenta materials on stacks or grounds | The project requires URP. Go to Edit > Project Settings > Graphics and ensure a URP Render Pipeline Asset is assigned. Check that the Settings/ folder contains valid URP assets. |
| Level 1 plays, but the Win screen reloads Level 1 instead of advancing | Verify LoseWinPanelManager.LoadNextLevel() calls LevelManager.AdvanceLevel() before reloading the scene. This is the production fix — the engine template's placeholder version only reloaded the scene without advancing the index. |
| Booster buttons stay dark / disabled | Check you're past the unlock level — +Moves needs level 2, Hint needs level 3 by default. Press U to force-unlock and refill all boosters for testing. |
| No sound | Open the SoundManager GameObject in GameNew.unity and verify each clip field has a .wav assigned from Assets/Hexa Away Puzzle 3D/Audio/. The masterVolume slider must also be above 0. |
| UI tap doesn't register | Verify there is exactly one EventSystem in the scene. HexaAwayGameManager.SetupGame creates one automatically if missing — if you removed that code path, restore it. Also: every overlay panel must carry its own Canvas with overrideSorting = true + a GraphicRaycaster, otherwise raycasts fall through to the board. |
| Auto generator produces "skipped" warnings | This means the multi-stage solvability loop failed to produce a solvable level for that slot. Open the console — the warning lists how many attempts were made. Try widening Error Margin or lowering Stacks / Level at the hard end of the curve. |
| Generated levels render off-screen at the top or bottom | The hard envelope is 11 columns × 24 rows. If you raised MaxRowSpan beyond 24 in LevelGenerator.cs, the camera frustum / orthographic size also needs to grow to match the taller grid. |
Resources/Levels/ folder before clicking the red "Delete ALL Levels" buttonIf you get stuck or have any issues, feel free to reach out to us at ragendom@gmail.com. We are happy to help!