
How to Make an App Like Subway Surfers

Building an endless runner like Subway Surfers is more technically involved than it appears. The game has been downloaded over 3 billion times and consistently sits in the top charts a decade after its 2012 launch. That staying power comes from tight engineering decisions made early — physics feel, procedural generation, monetisation hooks, and cross-platform performance. This post walks through what it actually takes to build something comparable.
What Kind of Game Engine Should You Use?
This is the first real decision and it shapes everything downstream. Unity and Unreal are the two realistic options for a production-grade endless runner at this scale. Godot is worth considering for smaller budgets, but its mobile export pipeline and asset ecosystem are thinner.
For Subway Surfers-style games, Unity (currently on Unity 6) is the practical choice. The reasons are specific:
- The Unity DOTS (Data-Oriented Technology Stack) with the Entity Component System (ECS) architecture handles thousands of game objects efficiently on mid-range Android hardware.
- Unity's Addressable Asset System lets you stream level chunks and character bundles without bloating the initial APK.
- The Unity Gaming Services stack (authentication, leaderboards, remote config) integrates cleanly without third-party glue.
Unreal Engine 5 gives you better out-of-the-box graphical fidelity, but its mobile performance overhead is real. On a Samsung Galaxy A-series device with an Adreno 610 GPU, an equivalent scene in Unreal will typically run at lower frame rates than Unity unless you've aggressively stripped the rendering pipeline. For a hyper-casual to mid-core endless runner, that trade-off rarely makes sense.
Physics and Character Controller
Subway Surfers doesn't use Unity's built-in Rigidbody physics for the player character. It uses a custom character controller. This matters because Rigidbody introduces simulation jitter and inconsistent collision timing that makes swipe controls feel unreliable at high speeds.
Write your own CharacterController-based movement system. Lane switching should use a lerp or a spring-damper interpolation over 0.1–0.15 seconds. Jump arcs should be tunable via a gravity multiplier on the downward phase — this is what gives jumps that satisfying "heavy" feel without making the character feel sluggish on the way up.
How Does Procedural Level Generation Actually Work?
The track isn't randomly generated per tile. It's chunk-based. You author 20–40 distinct track segments ("chunks") as prefabs, each 30–60 Unity units long, with metadata about obstacle density and type. The generation system pulls from a weighted pool at runtime, influenced by:
- Current score (difficulty ramp)
- Recent chunk history (avoid repeating the same chunk twice in a row)
- Active mission objectives (bias toward chunk types that surface relevant obstacles)
Each chunk is instantiated 2–3 chunks ahead of the player and destroyed 1 chunk behind. Object pooling is non-negotiable here. Instantiating and destroying GameObjects at 60fps will stutter on any device. Use Unity's ObjectPool<T> (available since Unity 2021) or write your own.
Obstacle placement within chunks can be authored manually or generated procedurally with constraints. Manual authoring gives designers control over difficulty curves. Procedural generation inside chunks scales content volume cheaply. Most shipped games do both: hand-authored chunks with procedurally selected obstacle variants within them.
Speed Scaling and Difficulty
Speed should increase on a curve, not linearly. A sigmoid or logarithmic ramp feels more natural to players. Start at 8–10 units/second and cap somewhere between 25–35 units/second. Beyond that, the reaction window for swipe inputs drops below 200 milliseconds, which crosses into genuinely unplayable territory for a significant portion of your player base.
/// Not sure where to start?
Get the architecture before you commit
Tell us what you're building and we'll map the technical approach, stack, and rough timeline. No cost, no obligation, no sales call required.
Monetisation Architecture: What Actually Makes Money
Subway Surfers runs a free-to-play model built on three pillars: rewarded video ads, IAP (in-app purchase) for the hoverboard currency ("keys" and "coins"), and cosmetic character/board unlocks. Understanding the split matters if you're building a competitor.
| Revenue stream | Typical share in casual mobile games | Implementation complexity |
|---|---|---|
| Rewarded video ads | 60–70% | Low — Unity Ads or AdMob SDK |
| IAP (currency packs) | 20–30% | Medium — StoreKit 2 on iOS, Google Play Billing v6 |
| Battle pass / season system | 5–15% | High — requires backend, live ops tooling |
Integrate Unity LevelPlay (formerly ironSource) or MAX by AppLovin for ad mediation. Direct SDK integrations with a single ad network leave money on the table; mediation layers run real-time auctions across networks and consistently produce 15–40% higher eCPMs.
For IAP, use RevenueCat rather than raw StoreKit/Play Billing. It normalises the two platforms' event models, handles receipt validation server-side, and gives you a single webhook stream into your analytics pipeline. The 1% revenue share is worth it at most scales below $10M annual revenue.
Cross-Platform Build and Performance Targets
The game needs to ship on iOS and Android. Unity's build pipeline handles this, but you need explicit performance budgets before you start building assets.
Target a stable 60 fps on hardware from 3 years ago. In 2025, that means an iPhone 12 (A14 Bionic) on iOS and a Snapdragon 720G on Android. On the low end, target 30 fps on a Snapdragon 450 device. Build your rendering budget around this:
- Draw calls: under 50 per frame (use GPU instancing for repeated obstacles and coins)
- Triangle count per chunk: under 100k
- Texture memory budget: under 150 MB on device
Use Unity's Frame Debugger and the Android GPU Inspector to profile on-device, not in the Editor. Editor performance numbers are meaningless for mobile.
For iOS, enable Metal rendering and use Unity's URP (Universal Render Pipeline) with the 2D renderer stack if your art style allows it. URP on mobile is materially faster than the built-in pipeline for this type of game.
Backend Requirements
An endless runner of this type needs a thin but real backend. At minimum: player save data (score, currency, unlocks), leaderboards, and remote config for tuning game variables without app store updates.
Firebase Realtime Database or Firestore handles the first two cheaply at low scale. For remote config, Firebase Remote Config works, but Unity Gaming Services Remote Config integrates more cleanly with the Unity workflow and supports A/B test assignment natively. At over 100k DAU, you'll want to move save data off Firebase and onto a proper managed database (PostgreSQL on Cloud SQL or Aurora) with a thin REST or gRPC service in front of it.
Conclusion
The core systems — chunk generation, object pooling, custom character controller, ad mediation, and a light backend — are all well-understood. None of them are particularly exotic. The real work is in the tuning: speed curves, swipe response times, difficulty ramps, and the monetisation balance that keeps players spending without killing retention.
If you're evaluating whether to build this in-house or partner with an external team, the honest question is whether you have mobile Unity engineers who have shipped a live-ops title before. The technical surface area is manageable, but experience with the Unity build pipeline, Apple and Google review cycles, and live ops tooling compresses timelines significantly.
The next step is a playable prototype of the core loop: movement, one chunk type, and object pooling. That prototype will tell you more about your team's readiness than any estimate will.
FAQ
How long does it take to build a game like Subway Surfers? A functional prototype with core mechanics takes 6–10 weeks with an experienced Unity team. A production-ready v1.0 with monetisation, backend, and store-quality assets typically takes 6–9 months. The long tail is live ops: content updates, seasonal events, and balance patches that run indefinitely post-launch.
What does it cost to develop an endless runner mobile game? Rough ranges: $80,000–$150,000 for an MVP with a small external team; $300,000–$600,000 for a polished launch-ready product with original art, audio, and a live-ops backend. The biggest variable is art production. Subway Surfers' visual style requires significant 3D modelling and animation work.
Do you need a separate codebase for iOS and Android? Not with Unity. A single C# codebase compiles to both platforms. You will have platform-specific configurations — provisioning profiles, signing certificates, StoreKit vs Play Billing SDK calls — but these are configuration concerns, not separate codebases. Expect to spend 10–15% of dev time on platform-specific plumbing.
Is Unity the only option, or can you use Godot or Unreal? Godot 4.x is viable for simpler 2D endless runners and has a much lighter export footprint, but its 3D mobile performance is behind Unity for this use case. Unreal is the wrong tool here unless you have a specific graphical target that requires it. Unity's mobile ecosystem depth, asset store, and UGS backend services make it the default correct choice in 2025.
How do you handle cheating and score manipulation on leaderboards? Client-side score reporting is always cheatable. Validate scores server-side by replaying the session deterministically or by checking that the reported score is within a statistical envelope for the reported play time and difficulty level. Flag outliers rather than blocking them immediately to avoid false positives. For high-stakes leaderboards, store a full input log and replay it server-side.
Have a project in mind? Contact Sodio Technologies to discuss your requirements and explore the right technology solution for your business.
/// Work with us
Talk to the engineers who'd build it
You'll get a technical scope, timeline and cost estimate from the people doing the work, not an account manager. In-house team, no subcontracting, since 2016.
