Case study · EA Frostbite

Zone Streamer

Designing a pattern that scales, not just a fix. A redesigned system for editing zone, neighbor, and volume relationships, anchored by a confirmation pattern that gives users visibility and control that didn't exist before.

The redesigned Zone Streamer editor: a hex-and-pentagon zone grid with Volume 2 highlighted in yellow, the ZoneStreamer panel showing Zones, Regions and Vistas tabs, Edit Zones / Edit Neighbours / Edit Volumes modes, and a Neighbour Volume Links list.
The redesigned Zone Streamer editor: one Volume selected, its zones and neighbour links visible in a single view.
Role
Principal / Staff UX Designer, embedded (in-house consultancy model)
Where
EA Frostbite, across the Battlefield and Skate engineering teams (codename: Scene)
When
January 2026 to present. Design complete, in engineering handoff. Targeting an early-October 2026 ship.
Scope
Zone, neighbor, and volume relationship editing, plus an independent AI-assistant exploration

The situation on arrival

30+

Configurations reassigned by hand every time the map changed.

3 → 30

Fine at three zones. Broken at thirty. The representation didn't scale.

Fully manual

No checkpoint, no review, no undo before commit.

The real problem

Zone Streamer handles how zones, think of them as hexagonal slices of a world map, their neighbors, and their groupings (called Volumes) stream together across a game world. A zone can represent something as small as a street intersection, used to trigger game logic: environmental procedures, camera or lighting setups, day-night cycles, weather patterns, whatever needs to change when a player crosses a threshold.

The tool predates this project. My team picked up this specific work in January 2026 after Battlefield developers asked for support improving it. A designer on that team had recorded himself manually reassigning neighbor-zone relationships across more than thirty configurations. Every time the map changed, he had to start over.

This wasn't a missing button. The underlying representation didn't scale: fine at three zones, broken at thirty, and real world maps run at double or triple digits of zones, reconfigured constantly as a level evolves.

The original Zone Streamer: a flat grid of zones over a building facade, one zone selected, with on-screen instructions for shift-click to expand a neighbour set, ctrl-click to clear, and hold to paint zones one at a time.
The original tool: neighbour sets edited one zone at a time, by hand.

The process

I got close to the actual workflow, not just the ticket. This was co-designed with two other engineers: I worked in Figma, VS Code, and Claude Code, while one engineer built a parallel prototype directly in HTML.

At one point we diverged without realizing it. I was heads-down in Figma while he explored an approach of his own. We reconverged the following week and reconciled the two directions into one shared reference we worked from for the rest of the build.

The shared Figma handoff board: a user-flow strip along the top, then columns of wireframes, a decision log and action-items panel dated June 24 2026, jam-session editor captures, and the confirmation-dialog frames, all on one canvas.
The shared reference board: flow, wireframes, decision log, and handoff frames on one canvas. Open to zoom.

The solution: Zones, Neighbors, and Volumes

The interface splits editing into three focused modes, Zones, Neighbors, and Volumes, where Volumes is the new capability: the ability to define and edit a grouping of zones as a single unit, rather than reassigning each zone's relationships one at a time.

Three copies of the ZoneStreamer panel side by side, each with a different mode active: Edit Zones, Edit Neighbors, and Edit Volumes, over the same hexagon zone grid.
Editing split into three focused modes: Zones, Neighbors, Volumes.

A confirmation pattern that didn't exist before

Underneath the three modes sits a full-width review screen: one more look at every zone, neighbor, and volume relationship about to be applied, before it's committed. What used to be a fully manual, unreviewable process now has a checkpoint.

The Apply Neighbours from Volumes dialog: every pending neighbour change listed and grouped by zone, additions in green and removals in red with a mini hex diagram for each, and Apply selected changes / Cancel buttons.
The review step: every pending change listed, grouped, and diffed before commit.

A note on ownership, precisely stated

I didn't invent the Neighbor Volumes concept. I led the experience design and strategy behind how it works and how it's presented. Any team managing zone-based world data can inherit this pattern automatically, which is the point: one team's problem becomes every team's solution.

Validating with real users

Design work is complete and heading into engineering handoff. Right now this is in phase-one usability testing: 11 people who have previously used Zone Streamer are reviewing a demo recording and test build, against a feedback gate closing this week to protect an early-October ship.

Feedback so far has largely been clarifying questions, with real positive support, validating the original ask: giving users the ability to modify zone-to-zone neighbor relationships and how zones group into volumes.

11

Prior Zone Streamer users in phase-one usability testing.

1 pattern

Designed to be inherited by any team managing zone-based world data.

Oct 2026

Target ship, with design complete and in handoff.

Reflection

Zone Streamer is the real work: shipping, validated with real users, built to be inherited by other teams. The assistant below is what I chose to build on top of it, on my own time, to show how I would think about this exact problem if it were actually my job.

Extra chapter · independent exploration

Exploring an AI assistant layer

Everything in this chapter is not commissioned and not on any roadmap. It's exploratory work I built independently, on my own time, on top of the real design work above. It's consistent with something a few other designers on our team have been experimenting with: what does AI-assisted workflow actually look like, applied to a real problem instead of just described?

The Zone Streamer editor with the AI assistant panel docked full-height on the right, idle, one Volume highlighted in yellow in the hex grid.
The assistant panel, docked into the real Zone Streamer editor. Every flow below runs inside this frame.

Two use cases, two kinds of decision

I built two scripted flows to demonstrate a retrieve, reason, flag-or-recommend interaction pattern for a technical artist working inside this tool.

UC1

Time-of-Day Calibration

A hard-rule case: a zone-crossing threshold conflicts with a fog-trigger dependency. There's exactly one correct resolution, so the assistant doesn't offer a bypass. A deliberate design choice, not an omission.

UC2

Weather and Lighting Pairing

A judgment-call case: a developer asks whether snow can fall during sunset lighting in a region, or whether that forces a winter profile. The assistant plans, checks three sources, and surfaces a conflict, but here the artist can deliberately override it, and that choice gets logged as intentional, not left looking like a mistake.

Both flows run the same loop: retrieve, reason, then flag or recommend. Step through the stages below, or watch the full recordings.

UC1 flow · Time-of-Day Calibration

AI assistant panel: the artist asks how many zone crossings trigger a time-of-day shift and what happens at a threshold of 8; the assistant begins searching zone timing rules.
Step 1 / 4 · Ask The artist asks a precise question. The assistant scopes it and starts retrieving.
Searched, 3 sources. The Zone Timing Ruleset card explains that time-of-day transitions fire every 6 zone crossings and share a buffering dependency with fog triggers in Zones 4 to 6.
Step 2 / 4 · Retrieve Three sources checked. The rule that matters: transitions fire every 6 crossings, tied to the Zones 4 to 6 fog trigger.
Reasoning about the 6 to 8 threshold change, a checked record confirming the fog trigger fires during the sunset window, and a flag offering a single action: apply fix, plus 2 crossing offset.
Step 3 / 4 · Flag It reasons, verifies the fog trigger against the sunset window, and flags one conflict. One correct fix, so one action is offered.
Fix applied: plus 2 crossing offset. A resolved banner reads: 1 dependency checked, 1 conflict found, 1 fix applied.
Step 4 / 4 · Resolved The fix runs. The banner records what happened: 1 dependency checked, 1 conflict found, 1 fix applied.
1 / 4

UC2 flow · Weather and Lighting Pairing

AI assistant panel: the developer asks whether snow can fall during sunset lighting or whether that forces a winter profile; the assistant lays out a three-step plan and starts the first tool call.
Step 1 / 4 · Plan The developer asks a judgment-call question. The assistant lays out a 3-step plan before touching anything.
Three named tool calls with results: search the environmental pairing guide, read the region config, check the seasonal content calendar.
Step 2 / 4 · Tools Three named tool calls run in sequence. Each result is shown in full, not just a summary.
Synthesis: sunset does not pair with snow, the region is non-winter, no override is scheduled. A flag offers three options: switch to winter profile, use light fog or overcast instead, or keep snow and mark it as an intentional override.
Step 3 / 4 · Flag It synthesizes a conflict and offers three options, including keeping the snow as a logged, intentional override.
Outcome applied: switch to winter profile. A resolved banner reads: 3 tools called, 1 conflict found, 1 action taken.
Step 4 / 4 · Resolved The artist picks Switch to winter profile. The banner records 3 tools called, 1 conflict found, 1 action taken.
1 / 4
UC1 walkthrough: time-of-day calibration, retrieve to applied fix. About 34 seconds, no audio.
UC2 walkthrough: weather and lighting pairing, plan to logged override. About 34 seconds, no audio.
That asymmetry is the point: not every AI decision should be enforced the same way. A hard technical dependency and a creative judgment call need visibly different treatment.

The pivot that mattered

The first version of this demo was a linear script on a timer. The content was fine, but it didn't read as an orchestrated agent doing anything.

I diagnosed seven concrete reasons why: no visible plan, no visible tool selection, sources named but never used, decorative "thinking" states bound to nothing, a flag that just appeared with no synthesis, dead-end actions, nothing persisting across a frozen frame. Then I rebuilt UC2 around the fix: plan, dispatch three named tool calls, synthesize, flag, execute and confirm.

A Figma exploration board titled Explorations: Zone Streamer AI Assistant, with six labelled sections of wireframes progressing low to high fidelity: the panel surface, UC1 the reasoning loop, UC2 the diagnosis, UC2 the rebuild, trust and authority, and context-aware chrome.
The exploration board: the panel surface, both use-case loops, and the UC2 rebuild, low to high fidelity.

How I worked with AI to build this

I ran the same plan-verify-checkpoint discipline on the AI coding agent that built this that the demo itself demonstrates for the end user. Every on-screen string traces back to a single source-of-truth document. If a beat's wording wasn't written there, the build stopped and asked instead of inventing it. Every decision, and why, is logged. Every step that ran is logged, in order.

A VS Code window: the Source Control panel shows a clean working tree and a commit graph of small, clearly-messaged commits; the editor has DECISIONS.md open on an entry recording a feature that was blocked rather than guessed, with tabs for PROMPT_LOG.md and CLAUDE.md.
DECISIONS.md, PROMPT_LOG.md, CLAUDE.md, and a disciplined commit history, in the repo.

Then I audited my own build

I didn't want to grade the work by feel. So I built a small audit dashboard that scores this build against 21 real evaluation criteria, each one checked against the actual running code, with nothing rounded up: ambiguous status gets marked partial, not covered.

It flagged an inconsistency between the two flows and told me where the last few hours were best spent before anyone else saw it.

The Zone Streamer AI Assistant Design Audit dashboard: a generated timestamp, four score tiles reading 6 covered, 11 partial, 2 missing, 2 not applicable, a coverage bar, view filters, a recommendations panel, and the first scored criterion.
The build's own audit tool: 21 criteria, scored against the running code.

Being precise about what this is

There's a single orchestrator dispatching a fixed sequence of tool calls: retrieve, reason, then flag or recommend. That's one coordinator running a sequence, not multiple autonomous agents negotiating, and the distinction matters more to me than claiming the more impressive-sounding version.

Each step's output in this demo is hand-authored rather than a live model call, by design: the goal was to demonstrate the interaction pattern and reasoning loop clearly. In production, each step would be a real tool call, potentially with different models depending on how much reasoning a given step needs.

Final thoughts

Two pieces of work, held to the same standard.

The design work

Zone Streamer is the part that ships. It started as a support request about one painful workflow and became a representation change: a way to edit a group of zones as a single unit, with a review step before anything commits. The pattern isn't scoped to one team. Any team managing zone-based world data inherits it. Design is complete and in engineering handoff, validated with eleven prior users, targeting an early-October ship.

The exploration

The assistant layer is the part I built to think out loud. It isn't commissioned and isn't on a roadmap. I wanted to show, not just claim, how I would approach an AI-assisted version of this tool: a retrieve, reason, flag-or-recommend loop that treats a hard technical rule and a creative judgment call differently, built with the same logged, checkpointed discipline I would expect from the feature itself. If this became my job, this is where I would start.