← Writing
SDK Architecture

Shipping one feature in lockstep across Unity, iOS & Android

Chartboost Mediation & Core Unity SDKs

When a developer calls one method in the Unity SDK, that call has to travel through a C# wrapper, cross into native Objective-C/Swift on iOS and Java/Kotlin on Android, invoke a network adapter, and return a result — with identical semantics on both platforms. Owning the Unity layer of a production ad-mediation platform means every feature is really three implementations that must stay in perfect lockstep, plus an ecosystem of 20+ ad-network adapters that all depend on that contract.

The seam

The C# API is the single source of truth for the public surface. Below it, thin, generated-where-possible bridges cross the managed↔native boundary — P/Invoke and callbacks to the iOS framework, JNI/`AndroidJavaObject` to the Android library. The trick is that consumers never see the seam: sync and async calls, callbacks, and error models look the same regardless of platform.

flowchart TD
  DEV[Game / Unity developer] --> API[Unity C# API
single public surface] API --> BR{Native bridge
FFI layer} BR -->|P/Invoke + callbacks| IOS[iOS SDK
Obj-C / Swift] BR -->|JNI / AndroidJavaObject| AND[Android SDK
Java / Kotlin] IOS --> ADI[Ad-network adapters] AND --> ADA[Ad-network adapters] API -. UPM / NuGet .-> DIST[(Distributed to studios)]

What "lockstep" actually requires

Why the boundary is a flat contract

Keeping the managed↔native boundary a narrow, well-specified seam is what makes three codebases behave like one. It's the same principle I'm exploring at a lower level in PlanetExplorer — a C++ core behind a flat C ABI, designed to be embedded anywhere without coupling.

Scale — 26 public packages, 646K+ downloads across npm and NuGet, shipped in lockstep and adopted from independent studios to industry leaders.
Unity · C#iOS · Obj-C/SwiftAndroid · Java/KotlinNative ↔ managed FFIAPI & versioning design