← All games

Example: Ashfall Courier

A delivery game about crossing a volcanic city before the ash buries the last road.

Fictional example project used to preview the layout. Every area is filled so you can see all sections.

Role
Producer, Narrative Designer & Gameplay Programmer
Type
Game jam
Status
Released
Period
2025
Team
4 people
Genre
Narrative action
Platforms
PC, Web
Engine
Unity
Production

Game Production

Ran the 48-hour jam plan, cut scope at the right moments and kept the team in sync.

Responsibilities

  • Defined the scope and a three-milestone plan
  • Ran stand-ups every 6 hours
  • Owned the build and submission

Highlights & results

  • Shipped on time with every core feature
  • Top 10% in "Theme" out of 900 entries
Methodology
Kanban with timeboxed milestones
Team coordinated
4 people

Documents

Tools

  • HacknPlan
  • Discord
  • Google Sheets

Evidence

Narrative

Narrative Design

Wrote the courier's radio dialogue and the notes players find along the routes.

Responsibilities

  • World premise and tone
  • 40 lines of branching radio dialogue

Highlights & results

  • Players quoted the ending in most reviews
Narrative structure
Linear core with branching radio calls

Script excerpt

DISPATCH: You're late again, courier. COURIER: The road's gone. I'm taking the rooftops. DISPATCH: ...Then don't look down. The ash remembers footsteps.

Full script / document ↗

Tools

  • Ink
Programming

Gameplay Programming

Built the movement controller and the dynamic ash system that closes roads over time.

Responsibilities

  • Character controller
  • Ash spread simulation on a grid

Highlights & results

  • Stable 60 FPS on the WebGL build

Systems implemented

  • Character controller with ledge grab
  • Grid-based ash spread
  • Delivery timer and scoring

Languages

  • C#

Technical challenge & solution

The ash spread made the WebGL build stutter. I moved it to a fixed tick spread across frames, which removed the spikes.

Code sample

void Tick()
{
    // Spread to a budget of cells per frame to avoid spikes.
    for (int i = 0; i < cellsPerFrame && frontier.Count > 0; i++)
    {
        var cell = frontier.Dequeue();
        foreach (var n in grid.Neighbours(cell))
            if (grid.TryIgnite(n)) frontier.Enqueue(n);
    }
}

Tools

  • Unity
  • C#