Skip to content
WARDLIGHT ikonuClient work2026

WARDLIGHT

Escape a dark dungeon with one continuous line of light. Lantern flames are your lives.

AndroidiOS
Let’s build something like this
WARDLIGHT game artwork 1
WARDLIGHT game artwork 2
GameAMG / 26
Project
Hallowmark
Our role
Game design · Architecture · Unity development
Duration
In development

01 / Behind the product

A real need. A considered solution.

01

Challenge

When a level generator applies rules first and tests solvability afterwards, two things happen: most candidates are thrown away and some unsolvable levels slip through the test. The client (Hallowmark) also wanted a measurable guarantee on top: proof that every level is solvable and identical for every player, plus analytics showing where players get stuck.

02

Approach

"Solution first, rules derived": the generator builds a valid Hamiltonian path, then derives every mechanic (arrows, walls, locks, embers, forbidden cells) from that path, so every level is solvable by construction. The seed is the level itself: seed = (uint)(level * 2654435761). The prototype’s generator was extracted verbatim to Node as the golden reference; the C# port is diffed against golden fixtures in EditMode.

The Wardlight.Core layer has zero UnityEngine references, enforced by asmdef. Ads, purchases, analytics and cloud sync sit behind interfaces, so the game runs in the editor with no SDKs. Cloud and analytics use REST rather than SDKs (IL2CPP-safe), and funnel events were added for the client’s question: which level the app was backgrounded on, and on which attempt the player was caught.

03

Result

3200 levels swept, 3200/3200 solvable; the same levels generated twice produce byte-identical output. The reports live in the repo and re-run on demand. 40/40 EditMode tests are green and a 34 MB release-ready Android bundle is built. The client approved the drag feel at the interim delivery; the seal effect, the Warden tension vignette, the Merchant shop and rewarded-ad placements landed in the second stage.

03 / Scope & details

The details make the experience.

  • 01

    3200 levels swept, all solvable by construction

  • 02

    Byte-identical output on regeneration

  • 03

    Zero UnityEngine dependency in the Wardlight.Core layer

  • 04

    Ads, purchases, analytics and cloud sync all behind interfaces

  • 05

    Funnel analytics built around the client’s question: which level was abandoned, on which attempt

Numbered wardsLantern flamesThe WardenOrthogonal line

Technology

Unity 6C#URPSupabase
Engine
Unity 6000.5
Languages
TR · EN
Level generation & validation

Deterministic generation

seed = (uint)(level * 2654435761)

3,200 levels swept

INSIDE THE PRODUCT

The engineering behind the interface.

Systems we built and concrete problems we addressed in this project.

01

The prototype is the golden reference

The oyna.html prototype’s generator was extracted verbatim to Node; the only change replaced searchHam’s wall-clock deadline with a fixed op cap (the determinism fix). Golden fixtures sit at every mechanic threshold, and GenerationParityTests diffs the C# generator against them.

02

Cloud and analytics without SDKs

Firebase and Supabase integrations use REST through UnityWebRequest; IL2CPP-safe with no bundle bloat. Anonymous auth, progress backup, raw event rows and the GA4 Measurement Protocol sit behind the same ICloudSync interface; an empty key simply means offline.

03

Drop-off is captured from two events

Backgrounding is listened for on both OnApplicationPause and OnApplicationFocus, because with Run-In-Background enabled the HOME key fires focus rather than pause; the event is deduped to log once. level_fail_caught carries the attempt count: the answer to the client’s "where do they get stuck" question.

Your idea could be next.

What could we build for you?

From a first release to a growing platform. Let’s plan the design, development and launch together.

Tell us about your project

From Türkiye to the US, UK, Australia and everywhere in between.