
Almost every asset pack claims to be mobile-friendly. Very few state a triangle count, and none state
a draw call count — which is the number that actually decides whether your game runs.
Draw calls matter more than triangles
This is the part most people have backwards. A modern mid-range phone renders a surprising number of
triangles without complaint. What it struggles with is the CPU cost of telling the GPU to draw things —
one call per material, per mesh, per pass.
A 140-piece environment kit where each piece has its own material is 140+ draw calls before you have
placed a character. The same kit sharing one atlased material can batch down to a handful.
So when evaluating a pack for mobile, the question is not “how many triangles” but “how many
materials”. A pack with one shared material across every mesh is worth more on mobile than a
lower-poly pack with forty.
Triangle budgets that hold up
| Element | Mid-range phone | Note |
|---|---|---|
| Hero character | 3,000–8,000 | The one thing worth spending on |
| Enemy or NPC | 800–2,500 | Many on screen at once |
| Environment prop | 150–800 | Crates, rocks, furniture |
| Building or large structure | 1,500–5,000 | Usually seen from one side |
| Whole scene visible at once | 80,000–150,000 | Where the budget is actually spent |
These are working numbers, not limits. A stylised game can sit well under them; a showcase piece can
exceed them on a flagship device and fail on everything else.
What actually costs frames
In rough order of impact on a mid-range device:
- Overdraw from transparency. Stacked translucent quads — particles, foliage cards,
UI layers — are the most common cause of a game running badly on mobile. Each layer re-shades every
pixel underneath. - Draw calls. See above. Materials, not meshes.
- Real-time shadows. Expensive, and often replaceable with a blob shadow or baked
lighting at a fraction of the cost. - Texture memory. 2K textures on background props exhaust memory long before
triangles become the problem. - Triangles. Genuinely last, unless something is wildly over-budget.
Vertex colours instead of textures
Well-built low-poly packs often use vertex colours rather than texture maps. Every mesh shares one
tiny material, and colour information lives in the geometry itself.
The benefits on mobile are substantial: almost no texture memory, trivial batching, and recolouring
is a vertex edit rather than a texture repaint. The trade-off is that you cannot have fine surface
detail — which suits the low-poly look anyway.
If a pack advertises vertex colours, that is a genuine mobile signal rather than a marketing one.
What to check before buying
- Triangle count per asset, stated. If it is not, ask.
- Material count across the pack. One shared material is the ideal.
- Texture resolution and atlas usage. A single 1K atlas beats forty 512px textures.
- LODs — less critical at low poly counts, but useful for dense scenes.
- A stated test device. “Tested at 60fps on a 2021 mid-range Android” means far more
than “optimised for mobile”.
Profiling before you optimise
Optimising without measuring wastes time on the wrong thing. Two numbers tell you where you actually
stand, and both are available in minutes.
Are you CPU or GPU bound?
This determines everything about what to fix. In Unity’s profiler, compare the CPU frame time against
the GPU frame time — whichever is higher is your bottleneck.
- CPU bound usually means draw calls, physics, or garbage collection. Reducing
polygons will not help. - GPU bound usually means overdraw, shader complexity, or resolution. Reducing draw
calls will not help.
On mobile, CPU bound is far more common, which is why the material and draw call advice matters more
than triangle counts.
Profile on the device, not the editor
Editor performance tells you almost nothing about a phone. The editor runs on desktop hardware with
different memory bandwidth, a different GPU architecture and no thermal limit.
Both Unity and Unreal support profiling a build running on a connected device. Use the oldest phone
you intend to support, and profile after ten minutes of play rather than immediately — thermal
throttling changes the numbers substantially, and it is what your players will experience.
Texture memory, the quiet limit
Memory exhaustion causes crashes rather than slowdowns, which makes it harder to diagnose and more
damaging when it happens.
Rough working figures for a mid-range device: aim to keep total texture memory under 300–500 MB. A
single uncompressed 2K texture is around 16 MB, so forty of them exhausts a budget before geometry is
considered.
What helps most:
- Compress everything. ASTC on modern Android and iOS, ETC2 as a fallback. Compressed
textures use a fraction of the memory and decompress in hardware. - Size textures by screen coverage. A prop the player never approaches does not need
2K. 512 or even 256 is frequently enough. - Atlas aggressively. One 2K atlas holding sixteen 512px textures uses less memory
than sixteen separate textures and produces far fewer draw calls. - Mipmaps on for anything seen at distance — they reduce both memory bandwidth and
shimmering.
Static batching and instancing
Two automatic optimisations worth understanding, because assets can prevent them from working.
Static batching combines non-moving objects sharing a material into one draw call.
Requires: objects marked static, and identical materials. A pack where every prop has its own material
cannot batch at all.
GPU instancing draws many copies of the same mesh in one call. Requires: identical
mesh, identical material, and instancing enabled on the material. Ideal for scattered props — rocks,
trees, debris.
Both depend on material sharing, which is why “how many materials” is the question to ask about a
mobile pack rather than “how many triangles”.
What to cut first when you are over budget
- Real-time shadows. The single most expensive feature on mobile. Baked lighting plus
blob shadows looks better than low-resolution real-time shadows and costs a fraction. - Transparent overdraw. Reduce particle screen coverage, trim particle quads, cap
simultaneous effects. - Post-processing. Bloom and ambient occlusion are expensive at mobile resolutions.
A colour grade is nearly free; the rest are not. - Resolution. Rendering at 0.8× and upscaling is often imperceptible and recovers
significant GPU time. - Draw calls, by merging materials and atlasing.
- Triangles, last, and usually unnecessary.
That order is deliberate. Most people start at the bottom of this list because polygon count is the
number they can see on a product page, and it is almost never the reason a mobile game runs badly.
Testing it yourself
Import the pack, build a scene at the density your game will use, and profile on the oldest device you
intend to support — not in the editor, which tells you almost nothing about mobile performance.
What to look at: draw calls and batches first, then overdraw, then triangles. If draw calls are in the
hundreds for a simple scene, the pack’s material setup is the problem and no amount of polygon reduction
will fix it.
Our 3D assets state triangle counts and material setup on
each product page. Performance questions are welcome on the
3D modelling board.
Overdraw: the cost you cannot see in the profiler’s triangle count
Mobile GPUs are fill-rate limited far more often than they are geometry limited, and overdraw is the fastest way to exhaust fill rate. Every transparent surface the renderer touches costs a full pass over the pixels it covers, whether or not anything ends up visible. A screen-filling particle effect made of ten overlapping alpha cards is drawing the screen ten times.
The usual offenders are foliage cards, smoke and dust effects, UI panels stacked behind one another, and any full-screen post-process. A low-poly scene that runs at 60fps in an empty field can drop to 25 when the player walks into a dust cloud, and the triangle count will not have moved.
Both engines have an overdraw visualisation mode. Turn it on, walk the level, and look for the areas that glow. That is a five-minute check that routinely finds more performance than a day of mesh optimisation.
Texture memory is usually the real ceiling
A mid-range phone gives your game a few hundred megabytes of graphics memory, and textures consume the overwhelming majority of it. Twenty 2048×2048 textures with mipmaps is roughly 350 MB uncompressed — enough on its own to have the operating system terminate the app on a device with 3 GB of RAM.
The fixes are unglamorous and effective. Use ASTC compression, which every modern mobile GPU supports, rather than shipping uncompressed. Halve texture resolution for anything the player never sees closer than a few metres. And check the maximum size override per platform, because a texture authored at 4096 for a desktop build will import at 4096 on mobile unless you tell it otherwise.
The reason this matters more for low-poly art than for realistic art is that low-poly assets often need very little texture detail to look right. A flat-shaded style can frequently run on a single small palette texture shared by dozens of meshes, which is the largest single performance advantage the style offers — and it is wasted if every asset arrives with its own 2K map.
Static and dynamic batching, and why they stop working
Batching combines many small meshes into a single draw call, which is where the low-poly style earns its reputation for performance. It is also fragile in specific ways worth knowing before you buy a pack.
Static batching requires the objects not to move and to share a material. Dynamic batching in Unity applies only to meshes under a low vertex threshold and also requires a shared material. GPU instancing needs identical meshes with a material that has instancing enabled. In all three cases, the material is the thing that breaks it: a pack where every prop has its own material with its own texture will produce one draw call per prop no matter how few triangles each one has.
When evaluating a pack, count materials rather than meshes. Forty props sharing two atlased materials is dramatically better than forty props with forty materials, and the second kind is common because it is easier to author.
Shadows and lights, which cost more than the geometry does
A single real-time shadow-casting light re-renders the shadow-casting geometry from the light’s point of view every frame. On mobile that is often the most expensive thing in the frame, and it scales with the number of lights, not with how good the scene looks.
The pattern that works on phones is one directional light with shadows, everything else baked or unshadowed, and a short shadow distance so only nearby objects are in the shadow pass. For a stylised low-poly look, baked lighting plus a light probe setup for moving objects is usually indistinguishable from real-time and costs a fraction of it.
Test on the phone you are actually targeting
The editor’s play mode runs on a desktop GPU with desktop memory and tells you almost nothing about mobile performance. Neither does a current flagship phone, which will run a badly optimised scene at 60fps and hide every problem until launch.
Pick a device around four or five years old as your reference, build to it early, and check the frame time there rather than in the editor. Thermal behaviour matters too: many phones run fine for ninety seconds and then throttle hard, so a performance test that lasts thirty seconds is measuring the wrong part of the curve.
