DEV Community

Cover image for From LayaAir to Cocos Creator: A Solo Dev's Engine Migration After iOS Builds Kept Crashing
Marvin Tang
Marvin Tang

Posted on

From LayaAir to Cocos Creator: A Solo Dev's Engine Migration After iOS Builds Kept Crashing

The debug build that wouldn't stop crashing

It was 2 AM. I had just spent five days trying to fix the same bug.

My game ran perfectly in the browser — 60 FPS, smooth animations, clean input handling. Then I'd run the iOS debug build and watch it crash within 30 seconds of launch. Sometimes on scene load. Sometimes mid-gameplay. Sometimes on a simple button tap.

No consistent stack trace. No clear reproduction path. Just crashes.

That week, I decided to migrate the entire project from LayaAir to Cocos Creator.

This post is about why I made that call, what the migration actually looked like as a solo developer, and what I'd tell anyone considering either engine today.

Why I chose LayaAir in the first place

When I started building browser-first games, LayaAir was an obvious pick:

  • Strong WebGL performance — genuinely fast in the browser, often beating Cocos and Phaser in my side-by-side tests
  • TypeScript-first — clean workflow, great autocomplete, sane codebase
  • Good for 2D casual games — which is exactly what I build
  • Active in the Chinese dev community — a lot of reference material if you can read it

For about 8 months, this was the right choice. My physics games and puzzle games shipped to the browser, loaded fast, and ran well on desktop and mobile browsers alike.

Where LayaAir shines: Web builds

Let me be fair to LayaAir. For web-only targets, it's still a solid engine:

  • Small runtime size
  • Fast startup
  • Good rendering performance on WebGL
  • Reasonable TypeScript DX

If I were building a game that would only ever run in a browser, I'd still consider it.

The problems started when I tried to go native.

Where it broke: iOS native builds

My goal was to ship the same game to iOS. LayaAir advertises native export to iOS via its build pipeline — in theory, you get an Xcode project from your web codebase.

In practice, the iOS output was unstable in ways I couldn't engineer around:

  • Debug builds crashed unpredictably. Same code that ran flawlessly in the browser would segfault on device, often with stack traces pointing into the engine's native layer, not my code.
  • Memory-related crashes during scene transitions, even in a simple project with minimal assets.
  • Inconsistent behavior between simulator and real device — a bug that reproduced on iPhone 14 might not show on the simulator, and vice versa.
  • Very limited English-language debugging resources. Most issue discussions were in Chinese, and even there, many reported bugs had no resolution.

I spent five full days trying to:

  1. Strip the project down to a minimal reproduction
  2. Experiment with different build configurations
  3. Try every combination of engine version and Xcode version I could find
  4. Post on forums and wait for responses that never came

The issue wasn't in my code. It was in the engine's native bridge. And as a solo developer, I don't have the budget — in time or money — to debug someone else's native runtime.

The switch decision

Here's the framing that helped me decide:

"How many more days am I willing to spend on a problem I can't see the bottom of?"

If the engine's iOS layer was buggy enough that a minimal project crashed, what would happen when I added monetization SDKs, more assets, more scenes?

I gave myself a budget: two more days. If I didn't have a stable build by then, I'd switch engines.

I didn't make it to day two.

Migrating to Cocos Creator

Cocos Creator was the natural alternative:

  • Also TypeScript-based
  • Similar scene/node/component architecture to LayaAir
  • 61% of top 100 WeChat mini games ship on Cocos — which tells me the native export pipeline is battle-tested
  • MIT-licensed and actively maintained
  • Broader international documentation

The migration took about 10 days of focused work for a medium-sized project (a merge-gacha tower defense with around 40 scenes).

Here's what actually transferred well and what didn't:

What was easy

  • Game logic and data structures — pure TypeScript business logic ported with minimal changes
  • Scene structure concepts — both engines use a tree of nodes with components attached. The mental model is nearly identical.
  • Asset pipeline — sprites, atlases, and audio imported cleanly

What needed rewriting

  • Scene transitions and lifecycle hooks — API names and timing differ enough that I rewrote all the transition code
  • Input handling — the event system is different; I consolidated my input layer into a single adapter module
  • UI layout — LayaAir and Cocos have different layout primitives. I redid most of my UI by hand.
  • Animation system — different timeline formats; I reimplemented the important ones

What surprised me

  • Cocos's editor is heavier but more stable. LayaAir IDE is lighter, but I hit editor crashes regularly. Cocos Creator's editor has held up through multi-hour sessions without issue.
  • The iOS export just worked. The first time I tried to build for iOS with Cocos Creator, it compiled, ran on device, and didn't crash. After five days of LayaAir debugging, this felt absurd.
  • Web performance is still good. I was worried I'd lose the web performance edge. In practice, for my 2D casual games, the difference is imperceptible.

Results after the switch

  • Cosmic Summon (my gacha merge tower defense) now runs on both browser and iOS from the same Cocos Creator project
  • Juicy Ricochet shipped to the App Store as an all-Cocos build
  • Zero engine-layer crashes since the migration
  • My development velocity actually increased once I was past the migration hump — the editor stability alone was worth it

What I'd tell someone in the same situation

A few things I learned the hard way:

1. Set a debugging budget before you start.
"I'll fix this bug eventually" is how you lose two weeks. Decide in advance how many days the problem is worth.

2. Engine problems in the native layer are usually not solvable as a user.
If the crash comes from inside the engine's C++ or Objective-C code and isn't fixed upstream, you're not going to fix it. Move on.

3. Web performance isn't the only metric.
I chose LayaAir partly because its benchmarks were great. But "faster in a controlled web benchmark" didn't matter when the iOS build didn't work at all.

4. Pick the engine that ships the platforms you need — not the one that ships the benchmark you like.
Cocos Creator wasn't the "fastest" engine on paper for my use case. But it shipped everywhere I needed to ship, and that turned out to be the only metric that mattered.

5. Don't mistake language comfort for engine fit.
Both engines use TypeScript. I liked LayaAir's API aesthetically. But aesthetic preference shouldn't outrank "my game crashes on the target platform."

Is LayaAir bad? No.

I want to be clear: LayaAir isn't a bad engine. For web-only projects it's still a reasonable choice, and I know developers shipping successful games on it.

My specific experience was with the iOS native export, which didn't work reliably for my project. Your mileage may vary, especially if you're targeting different platforms or a newer engine version.

But if you're a solo developer, and stability across platforms matters more to you than peak web benchmark performance — Cocos Creator is, in 2026, the safer bet.


Currently building: Cosmic Summon, a gacha merge tower defense live on browser and iOS.

More of my games: phyfun.com

What engine are you using for your indie game? Have you migrated between engines before? I'd love to hear how it went — drop a comment.

Top comments (1)

Collapse
 
imagebear profile image
Marvin Tang

Question for the room: anyone here actually shipped an iOS game using LayaAir's native export? If yes, I'd love to know:

Which LayaAir version?
Did you hit crashes on device that weren't present in the simulator?
How did you work around them?

Genuinely curious whether my experience was a worst case or typical.