# Melonjs Performance

Use this skill when a melonJS game drops frames, allocates heavily, or needs to scale...

- Repository: https://github.com/melonjs/melonJS (6430 stars)
- Category: Testing
- License: MIT
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add melonjs/melonJS --skill melonjs-performance -g -a claude-code -y`
Codex: `npx skills add melonjs/melonJS --skill melonjs-performance -g -a codex -y`
Cursor: `npx skills add melonjs/melonJS --skill melonjs-performance -g -a cursor -y`
Gemini CLI: `npx skills add melonjs/melonJS --skill melonjs-performance -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add melonjs/melonJS`

## Description

Use this skill when a melonJS game drops frames, allocates heavily, or needs to scale to many objects. Covers object pooling, draw-call batching, atlases, baking with CanvasRenderTarget, instancing, culling and alwaysUpdate, the debug plugin, and where the real costs are. Triggers on: performance, slow, frame rate, fps, lag, pool, pool.register, pool.pull, batching, draw calls, InstancedMesh, culling, alwaysUpdate, inViewport, CanvasRenderTarget, optimise, profiling, debug plugin, memory, render targets, hdr.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Performance

## Measure first

Register the debug plugin and read the numbers before changing anything:

```js
import { plugin } from "melonjs";
import { DebugPanelPlugin } from "@melonjs/debug-plugin";

await app.init();
plugin.register(DebugPanelPlugin, "debugPanel");
```

It reports frame time, draw calls, object counts, and can overlay collision
shapes and bounds. **Draw calls** is usually the number that matters.

## Batching: the biggest lever

Both GPU backends batch **across textures**, not just within one: the quad
batcher assigns each source image a texture unit and embeds the unit in the
vertex data, so several different images still flush as a single draw. The pool
is finite, the WebGL batcher gets `renderer.maxTextures` units (the
`maxTextures` application setting, `"auto"` = the device limit capped at 32), the
WebGPU batcher eight per segment. Overflow the pool and the batch flushes.

So the goal is not "one image" but "few state changes". What actually ends a
batch:

- **Overflowing the texture-unit pool**, pack sprites into a `TextureAtlas` and
  prefer one large tileset over several small ones, so a screenful of sprites
  fits inside the pool with room to spare.
- **Changing `blendMode`**, `setBlendMode` flushes before it touches GL state.
  Group by blend mode where you can.
- **Switching batcher**, interleaving primitives (`strokeRect`, `fillRect`,
  debug shapes) or meshes between sprites flushes the quad batcher and rebinds.
  Draw all the sprites, then all the primitives.
- **Binding a custom shader**, a `ShaderEffect` on the quad batcher also turns
  multi-texture batching *off* for the duration, dropping you back to one
  texture per draw.

The rest: https://github.com/melonjs/melonJS/blob/HEAD/packages/melonjs/skills/melonjs-performance/SKILL.md
