- Real Arduino sensors (buttons, dial, piezo)
- Chataigne middleware routing serial data to OSC
- Qualisys motion-capture system tracking chef hats
- Full physical kitchen setup
A motion-tracked cooking game where physical actions in a real kitchen translate to digital gameplay. Two teams race to complete pies using Arduino-powered stations, motion capture, and chaotic Overcooked-inspired mechanics.
Two teams of two players race to complete pies faster than their opponents. Players wear chef hats fitted with motion-capture markers that track their position in a physical kitchen space. Real cooking stations—complete with Arduino-powered cutting boards, frying pans, and ovens—translate physical actions into in-game progress. The goal: total immersion, where the line between physical and digital cooking blurs.
My Contributions: This case study focuses on the technical architecture I designed and implemented. The technical design was done collaboratively with Crystal Hicks, while all coding was completed by me. I also created shader systems for the game, documented separately:
Mr. Meow's Kitchen is built using a modular, event-driven architecture centered around singleton managers and inheritance hierarchies. The system emphasizes loose coupling between components, allowing us to iterate quickly and support complex multi-team gameplay with physical hardware integration.
┌─────────────┐
│ Arduino │ (Physical sensors)
└──────┬──────┘
│ Serial
┌──────▼──────┐
│ Chataigne │ (OSC routing)
└──────┬──────┘
│ OSC
┌──────▼──────────┐
│ ArduinoManager │ (Receives OSC, broadcasts events)
└──────┬──────────┘
│ Events (OnStrengthReceived, OnStirButtonPressed, etc.)
├────────┬────────┬────────┬────────┐
▼ ▼ ▼ ▼ ▼
CuttingStep FryStep OvenStep StepUI AudioManager
Rather than tightly coupling systems through direct references, we use C# events/delegates extensively. For example, ArduinoManager broadcasts OnStrengthReceived, OnStirButtonPressed, OnTemperatureReceived, while CookingStep emits OnStepCompleted and OnStateChanged. GameManager fires OnTeamWon and OnMatchStateChanged.
This pattern means a cooking step doesn't need to know about UI, audio, or recipe tracking—it just announces when it's completed and interested systems respond. This made adding features like audio feedback or progress bars simple; we just subscribed new listeners to existing events. This was a huge factor in our success during a rushed production time period of around 8 weeks.
We built reusable base classes that capture common patterns:
All station types inherit from this. Handles player detection, team checking, collision logic.
Subclasses: StepStation, TrashStation, PresentStation, SkinSelectionStation, TeamFormationStation
All minigames inherit from this. Manages ingredient delivery, Arduino action tracking, state machine, timers.
Subclasses: CuttingStep, FryPanStep, OvenStep
All cooking UI inherits from this. Handles show/hide animations, progress bar lerping, success/failure effects.
Subclasses: CuttingStepUI, FryPanStepUI, OvenStepUI
This meant we could implement the frying pan minigame by writing ~100 lines specific to stirring logic, while inheriting all the state management, ingredient handling, and Arduino integration for free.
IngredientData ScriptableObjects define:
This allows for easy configuration of ingredient behavior without touching code. As we playtested the game and made changes, it simplified the process of making minor tweaks that had major positive effects on gameplay!
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ TEAM A KITCHEN │ │ TEAM B KITCHEN │
│ │ │ │
│ ┌───────────────────────┐ │ │ ┌───────────────────────┐ │
│ │ RecipeManager (A) │ │ │ │ RecipeManager (B) │ │
│ │ IngredientManager (A)│ │ │ │ IngredientManager (B)│ │
│ │ CuttingStep (A) │ │ │ │ CuttingStep (B) │ │
│ │ FryPanStep (A) │ │ │ │ FryPanStep (B) │ │
│ │ OvenStep (A) │ │ │ │ OvenStep (B) │ │
│ └───────────────────────┘ │ │ └───────────────────────┘ │
│ │ │ │
│ OSC: /teamA/chop │ │ OSC: /teamB/chop │
│ /teamA/stir1 │ │ /teamB/stir1 │
│ /teamA/temperature │ │ /teamB/temperature │
└─────────────────────────────┘ └─────────────────────────────┘
One of our key architectural decisions was duplicating managers per team rather than centralizing with dictionaries. Each team has completely isolated instances: RecipeManager, IngredientManager, and all cooking step stations. This duplication keeps team state separate and prevents cross-contamination.
if (player.team != station.team) return;
ArduinoManager binds separate OSC addresses per team (/teamA/chop, /teamB/chop, etc.) and includes team info in events. Each cooking step filters events: "Is this for my team? If not, ignore."
When a player throws away an ingredient, the RecipeManager automatically resets all affected cooking steps:
Each IngredientData has a resetFromStep field. When destroyed, ingredients notify their team's RecipeManager, which cascades the reset. This prevents broken game states (e.g., frying step thinking you've chopped ingredients when you haven't).
┌───────────────┐
│ Skin Selection│ (Players walk to cat selection zones)
└───────┬───────┘
│
┌───────▼────────────┐
│ Team Formation │ (Players walk to Team A/B zones, wait 2s)
└───────┬────────────┘
│
┌───────▼────────────┐
│ Pre-Game Graphic │ (Chop! Fry! Bake! GO! animation)
└───────┬────────────┘
│
┌───────▼────────────┐
│ Match Racing │ (Cooking gameplay)
└───────┬────────────┘
│
┌───────▼────────────┐
│ Victory Screen │ (Team A/B Wins!)
└────────────────────┘
Three independent state machines coordinate gameplay:
Each manager only cares about its own state transitions. GameManager doesn't know about player selection. CookingStep doesn't know about win conditions. Clean separation of concerns.
StepUI<T> where T : CookingStep provides:
Each specific UI (cutting, frying, oven) inherits and adds ~50 lines for step-specific visuals (knife animations, pan stirring, dial rotation). The base class handles all the boilerplate.
One of the biggest challenges was developing a game that requires motion-capture hardware, physical Arduino controllers, and OSC networking. We built multiple testing layers so we could work anywhere:
We created in-game simulator panels that call ArduinoManager's simulation methods:
PlayerController has a debugMode flag that:
Impact: This infrastructure meant we could do the bulk of bug testing without the motion-capture lab. Most gameplay logic, UI, and Arduino integration was built and tested at desks with keyboard controls and Unity buttons. When we finally brought it to the lab, core systems worked immediately—we only needed to calibrate tracking offsets.
Our first major playtest revealed that while the core concept was fun, the execution had serious issues. Player feedback clustered around two main themes: clarity and pacing. Here are the critical design changes that resulted:
Core Problem: "I don't know what's going on"
Players were confused about game state, ingredient requirements, and what to do next. We addressed this through several interconnected changes:
All three cooking stations overlapping within kitchen space
Stations moved to separate parts of the kitchenette
Impact: When stations were overlapping, players were not sure which stations they were activating and didn't know how to get their ingredients to the right place. When we spread the stations out, it clarified the different steps and made each station feel like a distinct destination.
Generic star icons marked completion
Station-specific icons (knife, pan, oven) show which steps are complete
Impact: Stars were ambiguous; players couldn't quickly glance to see if they'd chopped, fried, or baked yet. Station icons became an instant visual language.
Each ingredient had separate "chopped" states
Chopping station outputs one universal "bowl of chopped ingredients"
Impact: Visual clutter reduction. Players don't care that the onion became "chopped onion"; they care that they've completed the chopping step. This simplified station gameplay and made the recipe flow clearer.
Oven used a horizontal progress bar
Circular dial UI that matches the physical potentiometer
Impact: When physical controllers don't match on-screen representation, players get confused, and the UI feels less reactive and less immersive. A dial controller should show a dial UI.
Players had to run to stations empty-handed to see what was needed
Recipe book panel appears when standing at present station without final ingredient, showing exactly what's needed for every step
Impact: Separating the recipe book from the regular stations increases the time players have to spend running between, which adds to the fun chaos we're aiming for. It also allows for more team collaboration. It works much better than the per-station approach, as it's far more difficult to be in the stations empty-handed than it is to be at the present station with a completed pie in your hands!
Core Problem: "It just feels too calm"
The game lacked urgency and tension. Players described it as "relaxing" when we wanted "frantic chaos." We needed to inject speed and consequence:
Chopping: Hit button 10 times, no failure
Frying: Stir for a few seconds, step completes
Constantly decaying progress bar for both stations
If bar hits zero, step fails, and ingredient is lost
Impact: Transformed minigames from rote actions into skill-based challenges. Physical effort intensity now directly correlates to success. Missing chops or sloppy stirring has consequences.
Pretty slow movement animation
Increased speed of movement
Impact: We found that with slow movement animations, players did not feel like they were in a rush to get around, despite being in an intense game. By increasing their movement speed in-game, we created the feeling of frantic rushing, which led to players following their in-game characters' lead!
Ingredients had slow, gentle bounce animations
Faster bounces + ingredients shrink over time (15-second despawn timer)
Impact: Visual urgency cues. Seeing ingredients shrink creates time pressure that makes the game much more exciting!
Overall Design Philosophy Shift: These pivots collectively moved us closer to our goal: a physical execution game where challenge came from speed, coordination, and not messing up under pressure. Much closer to our Overcooked inspiration!
Overall, this is my most complex and challenging project to date. I challenged myself at the beginning to not only learn new ways to connect different interfaces together, but also to not shy away from creating complicated, robust systems in code rather than going for the simple, band-aid-on-a-bullet-hole solution. I also picked up a lot of new and interesting fabrication skills and techniques along the way, many of which I want to continue to explore, like soldering and wood fabrication.
This project also reflects my interest in creating usable systems. I wanted to build early and build well; I finished the main game system by week 3. I created lots of helper functions and exposed a lot of parameters because I knew we would want to tweak as we went along, and I learned a lot about creating tools that are useful for people who aren't as comfortable with code as I built systems for the whole team to utilize.
Finally, I love the total immersion of this project. Using your body as a controller, using a physical kitchen, and connecting to a digital experience all at once really brings people all in on the fun, silly, and competitive spirit of the game.
To expand on this project in the future, I'd like to: