Past Work

Normal VR

Normal VR made tools and games for shared virtual worlds. I worked on the multiplayer systems behind Normcore, its Unity networking plugin, and helped bring Half + Half, its first game, to release.

Visit Normcore
Four colorful avatars swimming together among fish in Half + Half.
Swimming together in Half + Half.

Normal started with the possibility of being somewhere together. Avatars, drawing tools, a keyboard floating in space, a table-tennis game in the forest. These experiments gave us a way to explore what people might do when they shared a virtual world.

I joined in January 2017 and worked on the systems that kept those experiences connected. That work grew into Normcore, a multiplayer plugin for Unity, and later supported the release of Normal's first game, Half + Half.

A virtual keyboard in a shared 3D space.
Table tennis in the shared forest.

Joining a shared world meant coordinating a chain of services, from a party request to a ready room running the right server version. My work spanned:

  • Grouping Half + Half parties into games, with waiting, progress updates, cancellation and disconnect handling.
  • Finding existing Normcore rooms, using latency measurements to choose a region, and starting realtime servers through Kubernetes.
  • Scoping rooms to the right application and matching SDK versions to compatible server builds.
  • Connecting Unity's C# API to native C++ networking and Go services, including serialization, callbacks and connection lifetimes.
  • Coordinating room readiness, saved state, save retries and shutdown, including saves still in flight as the last player left.

My early work focused on persistence and synchronization. I moved the Python persistence service from a sharded Google Cloud Datastore implementation to MySQL on Cloud SQL, while keeping it on App Engine.

On the Unity side, the difficult cases often came down to timing. A player could leave before a newcomer had finished synchronizing. A version reply could arrive after the world had changed. An application could wait indefinitely to save before quitting. I worked through those cases and built a network stepper so we could inspect synchronization one operation at a time.

Avatars visible in Unity's scene and game panes.
Inspecting the shared avatar environment in Unity.

I built the Python account service behind NormalChat's web and desktop companion, working with Colby Ludwig on the connection to the frontend. Invitations, sign-in, display names and Steam access connected the account to the VR experience.

The service also needed the less visible parts of an invited-user product: password recovery, revocable sessions, administrative controls, account notifications and a maintenance-status response. I wrote migration tooling to replace email-based account keys with stable user IDs while preserving their invitation and Steam-key relationships.

I also built Backpack, a native iPhone companion prototype for browsing files, friends and rooms. It used GraphQL to bring those lists into a single interface, with file grids, downloads and previews.

Behind it, I developed the file-storage APIs, direct uploads and downloads through S3, and an AWS Lambda pipeline for image and video thumbnails. The service tracked file ownership and removed stored files and their thumbnails when they were no longer needed.

Later, I embedded Unity in the native app, handling its view and application lifecycle and writing an importer to bring Unity exports into the Xcode project. I also prototyped access through the iOS Files app. Backpack remained an experiment, with parts of the Files integration unfinished.

As Normcore developed, I built Go services to find and start multiplayer rooms on Google Cloud. The matcher could find an existing room or ask the client to measure candidate servers, choose a location, start a realtime server through Kubernetes, and wait for it to become ready. I connected that flow to Unity before the first alpha, then helped move it into the native plugin.

I built the backend for developer organizations, applications and their production and play keys. Those keys scoped room lookups to the right application. I carried SDK versions through the matching flow, mapped them to server builds, and later allowed compatible patch versions to share an existing room.

I worked across the C++ networking layer and the backend services that kept multiplayer rooms running. Much of that work involved making communication between them reliable across platforms.

I also helped rooms start and shut down cleanly, preserving their shared state as players joined and left.

I worked with Max and the team on matchmaking for Half + Half, then built the service that brought parties together to play. I connected it to Unity and the game's invitation system, and refined it through playtesting as we prepared for release.

The teaser below shows Half + Half's playful world.

Half + Half teaser excerpt.

I helped prepare the backend for launch as Normcore became a product other Unity developers could use. The public beta launched on May 7, 2019.

Half + Half launched on September 12, 2019 for Oculus Quest and Rift. In the run-up, I updated service deployment configurations; on launch day, I was working on blocked response handling in the matchmaker. This was a team effort, with Thomas Hahn working on related response and timeout fixes. I am credited alongside Colby under 2D Engineering. Later that month, the game appeared in the Oculus Connect 6 presentation.

First alphaNormcore SDK repository milestone
Public betaNormcore launches for Unity developers
Half + HalfReleased for Oculus Quest and Rift
Half + Half artwork in the Destinations and Rich Presence for developers presentation, with webcast overlays.
Half + Half in the Oculus presentation.
← All past work