Quick answer: Mobile optimization in Construct 3 comes down to reducing draw calls (fewer layers, batched sprites), compressing textures to stay under 2048x2048 per sheet, destroying off-screen objects, using touch-friendly input with virtual joysticks, and setting viewport scaling to Letterbox Scale. Profile with the built-in debugger to find your specific bottlenecks — it is almost always GPU fill rate or too many active objects.

A Construct 3 game that runs at a smooth 60 FPS on your development laptop can drop to 15 FPS on a mid-range phone. Mobile GPUs have a fraction of the rendering power of desktop GPUs, mobile CPUs throttle aggressively to save battery, and memory is limited. The good news is that Construct 3’s WebGL renderer is already well-optimized — most mobile performance problems come from how the game is structured, not from the engine itself. This guide covers the specific optimizations that make the biggest difference.

Reducing Draw Calls

Draw calls are the number of times the GPU is asked to render a batch of geometry per frame. On desktop, hundreds of draw calls are fine. On mobile, keeping draw calls under 50–80 per frame is critical for smooth performance.

Construct 3 automatically batches sprites that share the same texture and are on the same layer with the same blend mode. Every time the renderer encounters a different texture, a layer boundary, or a blend mode change, it has to issue a new draw call. Understanding this lets you structure your project to minimize draw calls.

// Draw call optimization strategies

// 1. MINIMIZE LAYERS
// Each layer adds at least one draw call.
// Merge layers that do not need independent scrolling or effects.
// BAD:  Background Layer, Ground Layer, Props Layer, Player Layer
// GOOD: Background Layer, Main Layer (ground + props + player)

// 2. USE SPRITE SHEETS
// Put related sprites on the same image sheet.
// In Project Properties > Advanced:
//   Sprite sheet mode: "Automatic"
// This packs sprites into shared textures for batching.

// 3. AVOID BLEND MODE CHANGES
// Keep all sprites on a layer at the same blend mode.
// One "Additive" sprite in a layer of "Normal" sprites
// breaks the batch and adds 2 extra draw calls.

// 4. Z-ORDER MATTERS
// Sprites with different textures interleaved in Z-order
// break batching. Group same-texture objects together in Z.

To see your current draw call count, open the debugger (press F12 in preview) and check the GPU profiler. The “Draw calls” counter shows exactly how many rendering batches are issued per frame.

Texture Compression and Memory

Mobile devices have limited GPU memory. Large textures consume VRAM and can cause the browser to evict textures from memory, leading to stuttering as they reload. Keep your total texture memory budget under 128 MB for broad device compatibility.

// Texture optimization checklist

// 1. SPRITE SHEET SIZE
// Keep sheets under 2048x2048 pixels.
// Many older devices fail on textures larger than this.
// Project Properties > Advanced > Max Sprite Sheet Size: 2048

// 2. REDUCE ANIMATION FRAMES
// A 24-frame run animation at 256x256 per frame
// = 24 * 256 * 256 * 4 bytes = 6.3 MB of VRAM
// Reduce to 8-12 frames for mobile without noticeable loss.

// 3. DOWNSCALE ASSETS
// On a phone screen, a 512x512 sprite and a 256x256 sprite
// are virtually indistinguishable. Halving dimensions
// reduces memory by 75%.

// 4. IMAGE FORMAT
// In Export settings, use "High quality" JPEG for backgrounds
// and "PNG" only for sprites that need transparency.
// JPEG backgrounds at 80% quality save significant space.

You can check your game’s estimated texture memory in the debugger under the “Object types” section. Each object type shows its image memory usage. Sort by memory to find the biggest offenders.

Touch Input and Virtual Controls

Mobile games need touch-friendly controls. The Touch plugin handles tap, hold, and swipe detection. For games that need directional movement, implement a virtual joystick:

// Virtual joystick implementation
// Create two sprites: JoystickBase (outer circle) and
// JoystickKnob (inner draggable circle)
// Pin JoystickBase to the bottom-left of the viewport

Touch: On touch start
Touch: Touch X < ViewportWidth / 3
    // Left third of screen = joystick areaSystem: Set JoystickActive to trueSystem: Set JoystickOriginX to Touch.XSystem: Set JoystickOriginY to Touch.Y

System: JoystickActive = true
System: Every tick
    // Calculate joystick offsetSystem: Set JoystickDX to
      clamp(Touch.X - JoystickOriginX, -50, 50) / 50System: Set JoystickDY to
      clamp(Touch.Y - JoystickOriginY, -50, 50) / 50
    // JoystickDX and DY are now -1 to 1JoystickKnob: Set position to
      (JoystickOriginX + JoystickDX * 50,
       JoystickOriginY + JoystickDY * 50)

// Apply joystick to player movement
System: JoystickDX > 0.3
    → Player: Simulate Platform pressing Right
System: JoystickDX < -0.3
    → Player: Simulate Platform pressing Left

Touch: On touch endSystem: Set JoystickActive to false

For a jump button, use a dedicated touch zone on the right side of the screen. A common pattern is left side for movement, right side for action buttons:

// Jump button (right side of screen)
Touch: On touch start
Touch: Touch X > ViewportWidth * 0.7
    → Player: Simulate Platform pressing Jump

Viewport Scaling and Screen Sizes

Mobile devices come in every aspect ratio imaginable. You need a scaling strategy that works across all of them without distortion or cut-off content.

// Viewport scaling options
// Set in Project Properties > Fullscreen Mode

// LETTERBOX SCALE (recommended for most games)
// Scales the viewport to fit the screen, adds black bars
// if the aspect ratio does not match. Guarantees all
// content is visible on every device.

// SCALE OUTER (good for action games)
// Fills the entire screen. Players with wider screens
// see more of the game world horizontally. No black bars,
// but UI elements must be anchored to viewport edges.

// LETTERBOX INTEGER SCALE (pixel art games)
// Scales by integer multiples only (1x, 2x, 3x).
// No sub-pixel filtering = crisp pixel art.
// May have larger black bars on some screens.

For UI elements that need to stay at screen edges (health bars, score text, virtual controls), use the Anchor behavior or set positions relative to ViewportLeft, ViewportRight, ViewportTop, and ViewportBottom expressions:

// Pin UI to viewport edges
System: Every tickScoreText: Set position to
      (ViewportRight("Game") - 10,
       ViewportTop("Game") + 10)
    → HealthBar: Set position to
      (ViewportLeft("Game") + 10,
       ViewportTop("Game") + 10)

Battery-Efficient Rendering

Mobile games drain battery fast if they are not careful about rendering. Players notice when your game makes their phone hot and the battery drops rapidly. Here are the key practices:

Limit particle counts. Desktop games can handle thousands of particles. On mobile, keep particle counts under 50–100 per emitter, and limit the total number of active particle objects to 2–3 at a time.

Avoid expensive shader effects. Blur, glow, and distortion effects are GPU-intensive. If you use them on mobile, apply them to small objects or static layers rather than full-screen. Better yet, pre-render the effect into the sprite image and skip the runtime shader entirely.

Destroy off-screen objects. Objects outside the viewport still consume CPU time for their behaviors and events. Destroy enemies, projectiles, and particles when they leave the screen:

// Destroy objects far outside the viewport
System: Every 0.5 seconds
    Bullet: Is outside layoutBullet: Destroy

    Enemy: Compare X <
      ScrollX - ViewportWidth - 200Enemy: Destroy

// Use object pooling for frequently created/destroyed objects
// Instead of Destroy + Create, move objects off-screen
// and reuse them. This avoids garbage collection pauses.

// Object pool: recycle a bullet
Bullet: Is outside layoutBullet: Set position to (-1000, -1000)Bullet: Set instance variable Active to falseBullet: Set Bullet speed to 0

// When you need a new bullet, pick an inactive one:
Bullet: Active = false
    → Bullet: Set position to (Player.X, Player.Y)Bullet: Set Active to trueBullet: Set Bullet speed to 600

Profile on real devices. The Construct 3 debugger shows performance metrics in the browser preview, but mobile Safari and Chrome have different performance characteristics. Use remote debugging (Chrome DevTools > Remote Devices) to profile directly on the target phone.

"The single biggest mobile optimization is reducing layers. I have seen games go from 20 FPS to 55 FPS just by merging four decorative layers into one. Each layer is a separate rendering pass, and that cost is enormous on mobile GPUs."

Related Issues

If your game has low FPS even after optimization, see Fix: Construct 3 Performance Low FPS Lag. For touch input not registering correctly, check Fix: Construct 3 Touch Input Not Working on Mobile. If particles are invisible on certain devices, see Fix: Construct 3 Particles Not Showing on Mobile. And if sprites flicker on mobile screens, see Fix: Construct 3 Sprite Flickering on Mobile Devices.

Profile on the weakest phone you can find. If it runs there, it runs everywhere.