{"id":482,"date":"2026-10-10T00:13:29","date_gmt":"2026-10-10T00:13:29","guid":{"rendered":"https:\/\/blog.cobwebgames.com\/?p=482"},"modified":"2026-10-10T00:13:29","modified_gmt":"2026-10-10T00:13:29","slug":"how-to-optimize-unity-games-for-mobile-hardware","status":"publish","type":"post","link":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware","title":{"rendered":"How to Optimize Unity Games for Mobile Hardware?"},"content":{"rendered":"[vc_row type=&#8221;full_width_background&#8221; full_screen_row_position=&#8221;middle&#8221; column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; scene_position=&#8221;center&#8221; text_color=&#8221;dark&#8221; text_align=&#8221;left&#8221; row_border_radius=&#8221;none&#8221; row_border_radius_applies=&#8221;bg&#8221; row_position_desktop=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; id=&#8221;sin_bg_pg&#8221; overlay_strength=&#8221;0.3&#8243; gradient_direction=&#8221;left_to_right&#8221; shape_divider_position=&#8221;bottom&#8221; bg_image_animation=&#8221;none&#8221; gradient_type=&#8221;default&#8221; shape_type=&#8221;&#8221;][vc_column column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; flex_gap_desktop=&#8221;10px&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;none&#8221; column_link_target=&#8221;_self&#8221; column_position=&#8221;default&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;2\/3&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221;][vc_row_inner column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; text_align=&#8221;left&#8221; row_position=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; pointer_events=&#8221;all&#8221; el_id=&#8221;row_01&#8243;][vc_column_inner column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; flex_gap_desktop=&#8221;10px&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;none&#8221; column_link_target=&#8221;_self&#8221; overflow=&#8221;visible&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/1&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221;][vc_column_text css_animation=&#8221;fadeInUp&#8221; css=&#8221;&#8221; text_direction=&#8221;default&#8221;]<span style=\"font-weight: 400;\">A phone has no fan. It has a slab of glass, a chip rated for a few watts of sustained load, and a battery that will happily turn into a hand warmer if you ask too much of it. Your Unity game ran at a glorious 60 frames per second in the editor on a desktop with a dedicated GPU. Ten minutes into a session on a mid-range Android phone, it runs at 24, and the device is hot enough to be uncomfortable. Nothing is broken. The hardware is behaving exactly as designed, and the game was never built for it.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This is a field manual for closing that gap. It is ordered the way an experienced team triages a slow build: measure first, find the real bottleneck, then fix things in order of payoff. Every number below comes from Unity&#8217;s own guidance or from widely cited mobile rules of thumb, and the rules of thumb are labeled as such, because the only budget that matters in the end is the one you measure on your lowest supported device.<\/span>[\/vc_column_text][\/vc_column_inner][\/vc_row_inner][vc_row_inner column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; text_align=&#8221;left&#8221; row_position=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; pointer_events=&#8221;all&#8221; el_id=&#8221;row_02&#8243;][vc_column_inner column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; flex_gap_desktop=&#8221;10px&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;none&#8221; column_link_target=&#8221;_self&#8221; overflow=&#8221;visible&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/1&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221;][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Heat Is the Real Frame Budget<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Desktop performance is a race. Mobile performance is an endurance event. A phone can hit its peak clock speeds for a short burst, then the system lowers them to keep temperatures safe, and your carefully tuned frame rate falls with it. This is thermal throttling, and it explains why a game can pass a two-minute benchmark and fail a thirty-minute playtest.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Two consequences shape every decision that follows. First, efficiency beats peak speed. A game that finishes each frame with spare time lets the chip idle between frames and stay cool. A game that barely makes 16 milliseconds will cook the device. Second, the target frame rate is a design choice with a thermal price tag. Unity defaults to 30 frames per second on mobile for good reason, and many successful titles stay there. Choosing 60 should be a decision you pay for, with a performance budget to match, rather than a default you inherit.<\/span>[\/vc_column_text][\/vc_column_inner][\/vc_row_inner][vc_row_inner column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; text_align=&#8221;left&#8221; row_position=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; pointer_events=&#8221;all&#8221; el_id=&#8221;row_03&#8243;][vc_column_inner column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; flex_gap_desktop=&#8221;10px&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;none&#8221; column_link_target=&#8221;_self&#8221; overflow=&#8221;visible&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/1&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221;][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Rule Zero:<\/b><span style=\"font-weight: 400;\"> Measure on the Device<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Profiling in the editor measures your workstation. Every optimization decision should come from a development build running on real hardware with the Profiler attached. Unity&#8217;s toolkit covers most of what you need:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Unity Profiler:<\/b><span style=\"font-weight: 400;\"> CPU usage, rendering, memory, and audio timelines, connected to a device over USB or the network.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Frame Debugger:<\/b><span style=\"font-weight: 400;\"> steps through a frame draw call by draw call so you can see exactly what is being rendered and why batches break.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Memory Profiler package:<\/b><span style=\"font-weight: 400;\"> snapshots of managed and native memory, with the ability to compare two snapshots and find leaks.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Platform tools:<\/b><span style=\"font-weight: 400;\"> Xcode Instruments on iOS, and Android Studio profilers or vendor GPU tools on Android, for GPU time, thermals, and power draw that Unity&#8217;s profiler cannot see.<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">One caution from experience: Deep Profiling mode adds overhead to every call and distorts the numbers. Use it to chase a specific script problem, then switch it off. For general work, stay with the standard profiler and judge frame time consistency instead of just average frame rate. A steady 30 frames per second feels better than an average of 45 that swings between 25 and 60.<\/span>[\/vc_column_text][\/vc_column_inner][\/vc_row_inner][vc_row_inner column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; text_align=&#8221;left&#8221; row_position=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; pointer_events=&#8221;all&#8221; el_id=&#8221;row_04&#8243;][vc_column_inner column_padding=&#8221;padding-3-percent&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; background_image=&#8221;17&#8243; background_image_position=&#8221;center center&#8221; background_image_stacking=&#8221;default&#8221; background_image_loading=&#8221;default&#8221; column_backdrop_filter=&#8221;none&#8221; font_color=&#8221;#FFFFFF&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;20px&#8221; column_link_target=&#8221;_self&#8221; overflow=&#8221;visible&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/1&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221; column_padding_type=&#8221;default&#8221; content_layout=&#8221;default&#8221; gradient_type=&#8221;default&#8221;][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2>What Can Actually Be Outsourced?<\/h2>\n<p><span style=\"font-weight: 400;\">Game art outsourcing covers a wide range of disciplines: 2D and 3D character design, environment art, UI and UX design, concept art, marketing and key art, animation, and technical art like rigging and shader work. A studio can outsource a single asset category or run an entire art pipeline through an external partner, depending on internal capacity and budget.<\/span>[\/vc_column_text][nectar_btn size=&#8221;medium&#8221; button_style=&#8221;regular&#8221; button_color_2=&#8221;Accent-Color&#8221; icon_family=&#8221;fontawesome&#8221; button_id=&#8221;b2&#8243; text=&#8221;Call To Action&#8221; url=&#8221;#&#8221; css_animation=&#8221;fadeInUp&#8221; icon_fontawesome=&#8221;fa fa-long-arrow-right&#8221;][\/vc_column_inner][\/vc_row_inner][vc_row_inner column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; text_align=&#8221;left&#8221; row_position=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; pointer_events=&#8221;all&#8221; el_id=&#8221;row_02&#8243;][vc_column_inner column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; flex_gap_desktop=&#8221;10px&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;none&#8221; column_link_target=&#8221;_self&#8221; overflow=&#8221;visible&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/1&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221;][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Know Your Frame Budget<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Everything starts with arithmetic. The time available per frame is one second divided by the target frame rate.<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><b>Target FPS<\/b><\/td>\n<td><b>Time Per Frame<\/b><\/td>\n<td><b>Typical Use<\/b><\/td>\n<\/tr>\n<tr>\n<td><b>30<\/b><\/td>\n<td><span style=\"font-weight: 400;\">33.3 ms<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Default mobile target, strategy, puzzle, casual, many 3D titles<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>60<\/b><\/td>\n<td><span style=\"font-weight: 400;\">16.7 ms<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Action games, racing, anything where input latency matters<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>90 or 120<\/b><\/td>\n<td><span style=\"font-weight: 400;\">11.1 ms or 8.3 ms<\/span><\/td>\n<td><span style=\"font-weight: 400;\">High refresh devices, usually for menus or simple scenes<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">\u00a0<\/span><span style=\"font-weight: 400;\">Your frame has to fit CPU work and GPU work inside that window, and the two run in parallel, so the slower side sets the pace. This is why the next step is working out which side is the bottleneck.<\/span>[\/vc_column_text][\/vc_column_inner][\/vc_row_inner][vc_row_inner column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; text_align=&#8221;left&#8221; row_position=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; pointer_events=&#8221;all&#8221; el_id=&#8221;row_02&#8243;][vc_column_inner column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; flex_gap_desktop=&#8221;10px&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;none&#8221; column_link_target=&#8221;_self&#8221; overflow=&#8221;visible&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/1&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221;][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Find the Bottleneck Before Touching Anything<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Optimizing the wrong side is the most common way to waste a week. If the GPU is the limit, reducing script cost changes nothing. If the CPU is the limit, shrinking textures does the same.<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><b>What You See in the Profiler<\/b><\/td>\n<td><b>Likely Bottleneck<\/b><\/td>\n<td><b>First Things to Try<\/b><\/td>\n<\/tr>\n<tr>\n<td><b>Main thread is full, GPU has idle time<\/b><\/td>\n<td><span style=\"font-weight: 400;\">CPU-bound<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Reduce draw calls and scripts, enable batching, pool objects<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Main thread waits on render thread or GPU<\/b><\/td>\n<td><span style=\"font-weight: 400;\">GPU-bound<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Reduce overdraw, resolution, shader cost, and shadow work<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Frame time spikes at irregular intervals<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Garbage collection<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Remove per-frame allocations, pool, enable incremental GC<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Game crashes or restarts after a few scenes<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Memory<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Memory Profiler, compress textures, unload unused assets<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Fine at first, slow after ten minutes<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Thermal throttling<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Lower sustained workload, lower frame rate target, adaptive quality<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">Run the check on your slowest supported device, not your best one. That device is the real specification.<\/span>[\/vc_column_text][\/vc_column_inner][\/vc_row_inner][vc_row_inner column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; text_align=&#8221;left&#8221; row_position=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; pointer_events=&#8221;all&#8221; el_id=&#8221;row_02&#8243;][vc_column_inner column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; flex_gap_desktop=&#8221;10px&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;none&#8221; column_link_target=&#8221;_self&#8221; overflow=&#8221;visible&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/1&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221;][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Rule One: <\/b><span style=\"font-weight: 400;\">Draw Calls Unity Spends Your CPU On<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Every draw call asks the CPU to prepare state and submit work to the GPU. On mobile, where CPU time is scarce, draw calls Unity issues per frame are the first suspect in most CPU-bound games. A commonly cited rule of thumb for mobile is to keep draw calls in the range of 50 to 100 for a typical scene. Treat that as a starting point and tune against your own profiling, since the real limit depends on the device, the render pipeline, and what else the CPU has to do.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Unity offers several tools to cut calls. Use them in this order:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>SRP Batcher.<\/b><span style=\"font-weight: 400;\"> In the Universal Render Pipeline, enable the SRP Batcher in the URP Asset under Advanced. It reduces the CPU cost of rendering many objects that share shader variants, even when it does not reduce the raw count of calls. Unity highlights it as a significant CPU rendering speedup.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>GPU instancing.<\/b><span style=\"font-weight: 400;\"> For a large number of identical meshes, such as foliage, crowds, or props, instancing draws them in one call. Enable it on the material.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Static batching.<\/b><span style=\"font-weight: 400;\"> Combines static meshes sharing a material into larger meshes. It reduces calls at the cost of more memory, so use it for level geometry, not for everything.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Dynamic batching.<\/b><span style=\"font-weight: 400;\"> Works only on small meshes. Unity&#8217;s guidance sets the limit at fewer than 900 vertex attributes and no more than 300 vertices per mesh, which excludes most modern characters and props. It also costs CPU to batch at runtime, so measure before leaving it on.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Texture atlasing.<\/b><span style=\"font-weight: 400;\"> Packing many small textures into one lets objects share a material and batch together. This is the standard fix for UI and 2D, and Sprite Atlases handle it automatically for sprites.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>GPU Resident Drawer.<\/b><span style=\"font-weight: 400;\"> In Unity 6, this feature moves instance batching to the GPU for object-dense scenes, with reported CPU rendering savings of up to half in the right conditions. It requires disabling static batching for the objects it handles, and it suits CPU-bound games with thousands of repeated objects.<\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400;\">Use the Frame Debugger to find out why batches break. The usual culprits are different materials, different shader keywords, objects crossing a lightmap boundary, and unnecessary transparency sorting. The tool names the reason for each break, which turns a mystery into a to-do list.<\/span>[\/vc_column_text][\/vc_column_inner][\/vc_row_inner][vc_row_inner column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; text_align=&#8221;left&#8221; row_position=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; pointer_events=&#8221;all&#8221; el_id=&#8221;row_02&#8243;][vc_column_inner column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; flex_gap_desktop=&#8221;10px&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;none&#8221; column_link_target=&#8221;_self&#8221; overflow=&#8221;visible&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/1&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221;][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Rule Two: <\/b><span style=\"font-weight: 400;\">Textures Are Usually the Memory Hog<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">On most mobile games, textures take the largest share of memory and a large share of bandwidth. Fixing them returns more per hour of work than almost anything else.<\/span><\/p>\n<p><b>Use ASTC.<\/b><span style=\"font-weight: 400;\"> Adaptive Scalable Texture Compression is Unity&#8217;s recommendation for both iOS and Android on modern devices. The older alternatives are PVRTC for iOS devices with A7 chips or older, and ETC2 for Android devices from before 2016. Compression is a stored-in-GPU-format decision, so it saves runtime memory and bandwidth, not just disk space. Commonly cited figures put the memory saving at up to about 75 percent compared with uncompressed textures, and Unity&#8217;s own asset guidance shows an uncompressed texture using almost 26 times the memory of a well-compressed equivalent with little visible difference.<\/span><\/p>\n<p><b>Cap Max Size.<\/b><span style=\"font-weight: 400;\"> A 4096 by 4096 texture on a phone with a 6-inch display is almost always wasted. A common range for mobile is 512 to 1024 pixels for most assets, with larger sizes reserved for hero items seen up close. Max Size in the import settings is non-destructive, so you can reduce it and judge the result on a device before committing.<\/span><\/p>\n<p><b>Turn off Read\/Write.<\/b><span style=\"font-weight: 400;\"> When enabled, Unity keeps a copy of the texture in both CPU-accessible and GPU memory, doubling the footprint. Leave it off unless a script has to read the pixels at runtime.<\/span><\/p>\n<p><b>Disable mipmaps where they have no use.<\/b><span style=\"font-weight: 400;\"> Textures that stay at a constant size on screen, such as UI and 2D sprites, do not need them. For 3D world textures, mipmaps save bandwidth and reduce shimmering, so leave them on.<\/span><\/p>\n<p><b>Check the 16-bit option.<\/b><span style=\"font-weight: 400;\"> If a compressed format causes visible banding on a specific asset, a 16-bit uncompressed texture can be a cheaper compromise than 32-bit.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The same discipline applies to meshes and animation. Turn off Read\/Write on meshes that do not need runtime access, and remove rigs, blend shapes, normals, and tangents from meshes that never use them. Mesh compression reduces disk size, though it does not shrink runtime memory, which surprises many teams. Our companion guide on the <\/span><a href=\"https:\/\/www.cobwebgames.com\/unity-game-development\"><span style=\"font-weight: 400;\">Unity asset pipeline<\/span><\/a><span style=\"font-weight: 400;\"> covers the import settings in depth.<\/span>[\/vc_column_text][\/vc_column_inner][\/vc_row_inner][vc_row_inner column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; text_align=&#8221;left&#8221; row_position=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; pointer_events=&#8221;all&#8221; el_id=&#8221;row_02&#8243;][vc_column_inner column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; flex_gap_desktop=&#8221;10px&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;none&#8221; column_link_target=&#8221;_self&#8221; overflow=&#8221;visible&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/1&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221;][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Rule Three: <\/b><span style=\"font-weight: 400;\">Unity Memory Optimization Is About Peaks<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Mobile operating systems kill apps that exceed their memory allowance, and they do it without warning. A typical rule of thumb puts a safe working budget somewhere in the 256 to 512 megabyte range for a game on mid-range hardware, though the actual limit varies by device and by operating system version. The worst case is the oldest, lowest-memory device you support, so budget against that one.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Effective Unity memory optimization focuses on peaks and leaks rather than averages:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Take snapshots with the Memory Profiler.<\/b><span style=\"font-weight: 400;\"> Capture one at the main menu, another after loading a level, and another after returning to the menu. Anything that grew and never shrank is a leak.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Unload what you are done with.<\/b><span style=\"font-weight: 400;\"> Scenes loaded additively, audio clips, and large textures should be released when a level ends. Unity does not always free assets on its own.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Stay away from the Resources folder.<\/b><span style=\"font-weight: 400;\"> Everything inside gets included in the build and indexed at startup, which hurts both size and launch time.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Use Addressables for large content.<\/b><span style=\"font-weight: 400;\"> The Addressable Asset System loads assets by address, asynchronously, from local storage or a remote content delivery network. It enables a smaller initial download and lets you stream levels, skins, and large audio on demand.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Mind your audio.<\/b><span style=\"font-weight: 400;\"> Long music tracks should stream from disk instead of loading fully into memory. Short, frequent effects can sit compressed in memory. Mono assets halve the footprint of anything that does not need stereo.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Watch the managed heap.<\/b><span style=\"font-weight: 400;\"> Unity&#8217;s garbage-collected memory only grows. Fragmentation can leave you with free space in total but no block big enough for a new allocation.<\/span><\/li>\n<\/ul>\n[\/vc_column_text][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Rule Four: <\/b><span style=\"font-weight: 400;\">Garbage Collection Hitches Feel Like Lag<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Managed allocations eventually trigger garbage collection, and a collection can freeze the main thread. Reported hitches range from a few milliseconds to 30 milliseconds or more on mobile, which is enough to drop one or two frames at 60. Players describe it as random stutter, and it is the main reason for mobile FPS Unity builds that look fine on average and feel bad in the hand.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The cure is to stop allocating during gameplay. The usual offenders:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>String concatenation in Update.<\/b><span style=\"font-weight: 400;\"> Cache strings, or use a StringBuilder, and avoid updating UI text when the value has not changed.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>LINQ and closures in hot paths.<\/b><span style=\"font-weight: 400;\"> They allocate. Use plain loops in code that runs every frame.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Instantiate and Destroy during play.<\/b><span style=\"font-weight: 400;\"> Replace them with object pools for bullets, effects, enemies, and anything spawned often.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>GetComponent and Find calls in Update.<\/b><span style=\"font-weight: 400;\"> Cache references in Awake or Start.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Boxing.<\/b><span style=\"font-weight: 400;\"> Passing value types into methods that take objects allocates on the heap.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Per-frame list and array creation.<\/b><span style=\"font-weight: 400;\"> Reuse collections and clear them instead of making new ones.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Unity also provides an incremental garbage collector, which spreads collection work across several frames to avoid one long pause. It reduces the severity of spikes, though it is no replacement for removing the allocations. Profile with the Memory section of the Profiler and look for the GC.Alloc column; any frame that allocates in steady state is a bug worth fixing.<\/span>[\/vc_column_text][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Rule Five: <\/b><span style=\"font-weight: 400;\">Overdraw, Shadows, and Resolution<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">When the GPU is the bottleneck on mobile, the cause is almost always fill rate. Phones render at very high pixel counts on small chips, and each pixel costs shader work. Three habits protect it.<\/span><\/p>\n<p><b>Reduce overdraw.<\/b><span style=\"font-weight: 400;\"> Layers of transparent sprites, particles, and UI stack up and force the GPU to shade the same pixel multiple times. Use the Scene view overdraw mode to find the worst areas, prefer opaque or alpha-tested materials where possible, and keep particle counts and sizes under control. Mobile GPUs use tile-based rendering, which handles opaque overdraw efficiently but punishes heavy transparency.<\/span><\/p>\n<p><b>Spend shadows carefully.<\/b><span style=\"font-weight: 400;\"> Real-time shadows are expensive. Limit shadow distance, use a single cascade or none, restrict shadow casters to important lights, and consider fake shadows for small objects, such as a blurred texture on a simple mesh under a character. Bake lighting for static scenes wherever possible.<\/span><\/p>\n<p><b>Lower the render resolution.<\/b><span style=\"font-weight: 400;\"> Many modern phones have screens far denser than anything a player can distinguish in motion. In URP, the Render Scale setting lets you render at 80 or 90 percent of native resolution and upscale, which saves a large share of GPU time with little visible loss. Resolution scaling is one of the highest-return fixes for a GPU-bound game, and it can be adjusted dynamically.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Also review the cost of cameras and post-processing. Unity notes that each camera can use up to about a millisecond of CPU time on lower-end platforms, so avoid extra cameras and full-screen effects that you do not need. Bloom, depth of field, and color grading at full resolution are expensive on phones, and a stripped-down set of effects often looks nearly identical.<\/span>[\/vc_column_text][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Rule Six:<\/b><span style=\"font-weight: 400;\"> Choose a Frame Rate You Can Keep<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Locking a frame rate is a design decision, and the right answer depends on the game. Set it explicitly with Application.targetFrameRate and manage vertical sync with QualitySettings.vSyncCount, because Unity&#8217;s mobile defaults can differ from what you expect, and leaving it unset hands the decision to the platform.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Practical guidance for this layer:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Match the rate to the genre.<\/b><span style=\"font-weight: 400;\"> Action and racing games benefit from 60. Puzzle, card, and many strategy titles look and play perfectly at 30 and run cooler.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Offer a quality toggle.<\/b><span style=\"font-weight: 400;\"> A 30 and 60 option in settings lets players choose between smoothness and battery life.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Drop dynamically when the device heats up.<\/b><span style=\"font-weight: 400;\"> Unity&#8217;s Adaptive Performance package, built with device makers such as Samsung, exposes thermal and performance state so the game can lower resolution or effect quality before the system throttles it for you.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Respect low battery.<\/b><span style=\"font-weight: 400;\"> When the player is under roughly 20 percent charge, a lower frame rate can extend a session considerably.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Run menus at lower rates.<\/b><span style=\"font-weight: 400;\"> A static menu has no reason to spend 60 frames per second of heat.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">The goal is a smooth, steady experience over a full session, which often means a lower target than the peak a device can theoretically reach.<\/span>[\/vc_column_text][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Rule Seven: <\/b><span style=\"font-weight: 400;\">Build Settings That Pay for Themselves<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">A few project-level settings change performance without touching a line of game code:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>IL2CPP scripting backend.<\/b><span style=\"font-weight: 400;\"> It compiles C# to native code, generally giving better runtime performance than Mono, and it is required to ship 64-bit ARM builds. Google Play requires 64-bit support for new apps.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>ARM64 architecture.<\/b><span style=\"font-weight: 400;\"> Target it for current phones.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Managed code stripping.<\/b><span style=\"font-weight: 400;\"> Removes unused code from the build to reduce size, with care around reflection.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Graphics API choice.<\/b><span style=\"font-weight: 400;\"> Vulkan can lower CPU overhead on capable Android devices, with OpenGL ES as a fallback for older ones. Test on both.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Strip unused shaders and variants.<\/b><span style=\"font-weight: 400;\"> Shader variants multiply quickly and bloat both build size and load time.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Quality levels.<\/b><span style=\"font-weight: 400;\"> Define separate quality tiers for low, mid, and high devices and choose between them at startup based on hardware.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">These are the quiet wins of a Unity performance optimization pass, and they often return more than weeks of scripting work.<\/span>[\/vc_column_text][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Build a Real Device Matrix<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">You cannot optimize for hardware you have never held. A practical test matrix for a global release covers at least these cases:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><b>Device Class<\/b><\/td>\n<td><b>Why It Matters<\/b><\/td>\n<\/tr>\n<tr>\n<td><b>Oldest supported iPhone<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Sets the iOS memory and performance floor<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Low-end Android with 3 to 4 GB of memory<\/b><\/td>\n<td><span style=\"font-weight: 400;\">The most common cause of crashes and poor reviews<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Mid-range Android, current generation<\/b><\/td>\n<td><span style=\"font-weight: 400;\">The largest share of real players<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Current flagship<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Confirms high-quality tiers and high refresh rates<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Tablet<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Catches layout and resolution problems<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">\u00a0<\/span><span style=\"font-weight: 400;\">Run each for a full thirty-minute session and record frame time, temperature, and battery drain, not just launch performance. If a device cannot hold the target, either lower the quality tier for that class or raise the minimum specification. Teams that skip this step find out from one-star reviews. Our<\/span><a href=\"https:\/\/www.cobwebgames.com\/game-testing\"> <span style=\"font-weight: 400;\">game testing<\/span><\/a><span style=\"font-weight: 400;\"> practice builds device matrices around the actual install base of a target market.<\/span>[\/vc_column_text][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h1><b>Cobweb Games&#8217; Approach to Unity Mobile Optimization<\/b><\/h1>\n<p><span style=\"font-weight: 400;\">Unity mobile optimization at Cobweb Games begins with a performance budget written during pre-production, before an asset is built: target devices, target frame rate, memory ceiling, and draw call and triangle budgets per scene. Every artist and engineer works against that document, and profiling on real devices happens at every milestone instead of in the final weeks. Studios exploring <\/span><a href=\"https:\/\/www.cobwebgames.com\/unity-game-development\"><span style=\"font-weight: 400;\">Unity game development<\/span><\/a><span style=\"font-weight: 400;\"> with us get a build pipeline where performance regressions show up the week they are introduced.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">For projects aimed at phones and tablets, the same discipline extends into <\/span><a href=\"https:\/\/www.cobwebgames.com\/mobile-game-development\"><span style=\"font-weight: 400;\">mobile game development<\/span><\/a><span style=\"font-weight: 400;\"> planning, including thermal strategy, tiered quality settings, and store-ready build configuration. Fixing performance late is expensive. Building to a budget from the start is cheap.<\/span>[\/vc_column_text][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h2><b>Common Unity Mobile Optimization Mistakes<\/b><\/h2>\n<p><b>Profiling in the editor.<\/b><span style=\"font-weight: 400;\"> The editor measures your desktop, not a phone.<\/span><\/p>\n<p><b>Optimizing the wrong side.<\/b><span style=\"font-weight: 400;\"> Spending a week on scripts in a GPU-bound game changes nothing on screen.<\/span><\/p>\n<p><b>Shipping max-size textures.<\/b><span style=\"font-weight: 400;\"> Oversized textures waste memory and bandwidth on every device.<\/span><\/p>\n<p><b>Ignoring heat.<\/b><span style=\"font-weight: 400;\"> A game that passes a short test and throttles at minute ten will still get reviewed at minute ten.<\/span><\/p>\n<p><b>Allocating in Update.<\/b><span style=\"font-weight: 400;\"> Per-frame garbage creates the stutter players describe as random lag.<\/span><\/p>\n<p><b>Testing only on flagships.<\/b><span style=\"font-weight: 400;\"> The device that crashes is always the one nobody tested.<\/span><\/p>\n<p><b>Leaving frame rate to chance.<\/b><span style=\"font-weight: 400;\"> Unset targets mean the platform picks for you.<\/span>[\/vc_column_text][\/vc_column_inner][\/vc_row_inner][vc_row_inner column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; text_align=&#8221;left&#8221; row_position=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; pointer_events=&#8221;all&#8221; el_id=&#8221;row_02&#8243;][vc_column_inner column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; flex_gap_desktop=&#8221;10px&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;none&#8221; column_link_target=&#8221;_self&#8221; overflow=&#8221;visible&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/1&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221;][vc_column_text css=&#8221;&#8221; text_direction=&#8221;default&#8221;]\n<h1><b>Frequently Asked Questions<\/b><\/h1>\n<p><b>What is the most effective first step in Unity mobile optimization?<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Profile a development build on a real low-end device and identify if the CPU or the GPU is the bottleneck. Every fix after that depends on the answer, and optimizing the wrong side wastes time.<\/span><\/p>\n<p><b>How many draw calls is too many on mobile?<\/b><\/p>\n<p><span style=\"font-weight: 400;\">A commonly cited rule of thumb is 50 to 100 for a typical scene, though the true limit depends on the device, the render pipeline, and the rest of the frame&#8217;s CPU work. Use the SRP Batcher, instancing, and atlasing, then measure on hardware.<\/span><\/p>\n<p><b>Should a mobile Unity game target 30 or 60 FPS?<\/b><\/p>\n<p><span style=\"font-weight: 400;\">It depends on the genre. Unity defaults to 30 on mobile, which suits puzzle, strategy, and many 3D titles and runs cooler. Action and racing games usually justify 60 and the performance budget that comes with it.<\/span><\/p>\n<p><b>Why does my game run fine for a few minutes and then slow down?<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Thermal throttling. The device lowers its clock speeds to control heat. Reducing sustained workload, lowering the target frame rate, or using Adaptive Performance to scale quality prevents it.<\/span><\/p>\n<p><b>Which texture format should I use for mobile in Unity?<\/b><\/p>\n<p><span style=\"font-weight: 400;\">ASTC for modern iOS and Android devices. PVRTC and ETC2 remain fallbacks for very old iPhones and pre-2016 Android devices respectively, which most projects no longer need to support.<\/span><\/p>\n<p><b>Does turning on dynamic batching improve performance?<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Only for very small meshes, under 300 vertices and 900 vertex attributes, and it costs CPU to run. In most modern projects, the SRP Batcher and GPU instancing do more, so test before leaving dynamic batching enabled.<\/span>[\/vc_column_text][\/vc_column_inner][\/vc_row_inner][\/vc_column][vc_column column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; sticky_content=&#8221;true&#8221; sticky_content_functionality=&#8221;js&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;large_depth&#8221; column_border_radius=&#8221;10px&#8221; column_link_target=&#8221;_self&#8221; column_position=&#8221;default&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/3&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221; column_padding_type=&#8221;default&#8221; content_layout=&#8221;default&#8221; gradient_type=&#8221;default&#8221;][vc_row_inner column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; text_align=&#8221;left&#8221; row_position=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; pointer_events=&#8221;all&#8221; el_id=&#8221;innr_02&#8243;][vc_column_inner column_padding=&#8221;padding-3-percent&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221; desktop_text_alignment=&#8221;default&#8221; tablet_text_alignment=&#8221;default&#8221; phone_text_alignment=&#8221;default&#8221; background_color=&#8221;#1E1E1E&#8221; background_color_opacity=&#8221;1&#8243; background_hover_color_opacity=&#8221;1&#8243; column_backdrop_filter=&#8221;none&#8221; column_shadow=&#8221;none&#8221; column_border_radius=&#8221;10px&#8221; column_link_target=&#8221;_self&#8221; overflow=&#8221;visible&#8221; gradient_direction=&#8221;left_to_right&#8221; overlay_strength=&#8221;0.3&#8243; width=&#8221;1\/1&#8243; tablet_width_inherit=&#8221;default&#8221; animation_type=&#8221;default&#8221; bg_image_animation=&#8221;none&#8221; border_type=&#8221;simple&#8221; column_border_width=&#8221;none&#8221; column_border_style=&#8221;solid&#8221; column_padding_type=&#8221;default&#8221; content_layout=&#8221;default&#8221; gradient_type=&#8221;default&#8221;][vc_raw_html css=&#8221;&#8221; el_class=&#8221;sidebar_dyn&#8221;]JTNDaDIlM0VUYWJsZSUyMG9mJTIwQ29udGVudHMlM0MlMkZoMiUzRSUwRCUwQSUzQ3VsJTIwaWQlM0QlMjJkeW5hbWljLXRvYy1saXN0JTIyJTNFJTNDJTJGdWwlM0U=[\/vc_raw_html][\/vc_column_inner][\/vc_row_inner][\/vc_column][\/vc_row]\n","protected":false},"excerpt":{"rendered":"<p>[vc_row type=&#8221;full_width_background&#8221; full_screen_row_position=&#8221;middle&#8221; column_margin=&#8221;default&#8221; column_direction=&#8221;default&#8221; column_direction_tablet=&#8221;default&#8221; column_direction_phone=&#8221;default&#8221; scene_position=&#8221;center&#8221; text_color=&#8221;dark&#8221; text_align=&#8221;left&#8221; row_border_radius=&#8221;none&#8221; row_border_radius_applies=&#8221;bg&#8221; row_position_desktop=&#8221;default&#8221; row_position_tablet=&#8221;inherit&#8221; row_position_phone=&#8221;inherit&#8221; overflow=&#8221;visible&#8221; id=&#8221;sin_bg_pg&#8221; overlay_strength=&#8221;0.3&#8243; gradient_direction=&#8221;left_to_right&#8221; shape_divider_position=&#8221;bottom&#8221; bg_image_animation=&#8221;none&#8221; gradient_type=&#8221;default&#8221; shape_type=&#8221;&#8221;][vc_column column_padding=&#8221;no-extra-padding&#8221; column_padding_tablet=&#8221;inherit&#8221; column_padding_phone=&#8221;inherit&#8221; column_padding_position=&#8221;all&#8221; flex_gap_desktop=&#8221;10px&#8221; column_element_direction_desktop=&#8221;default&#8221; column_element_spacing=&#8221;default&#8221;&#8230;<\/p>\n","protected":false},"author":1,"featured_media":483,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27],"tags":[],"class_list":["post-482","post","type-post","status-publish","format-standard","has-post-thumbnail","category-unity-game-development"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Unity Mobile Optimization: Draw Calls, Memory &amp; FPS Guide<\/title>\n<meta name=\"description\" content=\"A field manual for Unity mobile optimization: profile on device, cut draw calls, fix memory and GC spikes, and hold a stable frame rate without overheating.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Unity Mobile Optimization: Draw Calls, Memory &amp; FPS Guide\" \/>\n<meta property=\"og:description\" content=\"A field manual for Unity mobile optimization: profile on device, cut draw calls, fix memory and GC spikes, and hold a stable frame rate without overheating.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware\" \/>\n<meta property=\"og:site_name\" content=\"Cobweb Games\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-10T00:13:29+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.cobwebgames.com\/wp-content\/uploads\/2026\/10\/Optimizing-Unity-Games-for-Mobile.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1672\" \/>\n\t<meta property=\"og:image:height\" content=\"941\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Zain Khan\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Zain Khan\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutes\" \/>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Unity Mobile Optimization: Draw Calls, Memory & FPS Guide","description":"A field manual for Unity mobile optimization: profile on device, cut draw calls, fix memory and GC spikes, and hold a stable frame rate without overheating.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware","og_locale":"en_US","og_type":"article","og_title":"Unity Mobile Optimization: Draw Calls, Memory & FPS Guide","og_description":"A field manual for Unity mobile optimization: profile on device, cut draw calls, fix memory and GC spikes, and hold a stable frame rate without overheating.","og_url":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware","og_site_name":"Cobweb Games","article_published_time":"2026-10-10T00:13:29+00:00","og_image":[{"width":1672,"height":941,"url":"https:\/\/blog.cobwebgames.com\/wp-content\/uploads\/2026\/10\/Optimizing-Unity-Games-for-Mobile.webp","type":"image\/webp"}],"author":"Zain Khan","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Zain Khan","Est. reading time":"16 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware#article","isPartOf":{"@id":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware"},"author":{"name":"Zain Khan","@id":"https:\/\/blog.cobwebgames.com\/#\/schema\/person\/8f8a3c56d95587bfb360f183ab46e7bb"},"headline":"How to Optimize Unity Games for Mobile Hardware?","datePublished":"2026-10-10T00:13:29+00:00","mainEntityOfPage":{"@id":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware"},"wordCount":5528,"image":{"@id":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware#primaryimage"},"thumbnailUrl":"https:\/\/blog.cobwebgames.com\/wp-content\/uploads\/2026\/10\/Optimizing-Unity-Games-for-Mobile.webp","articleSection":["Unity Game Development"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware","url":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware","name":"Unity Mobile Optimization: Draw Calls, Memory & FPS Guide","isPartOf":{"@id":"https:\/\/blog.cobwebgames.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware#primaryimage"},"image":{"@id":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware#primaryimage"},"thumbnailUrl":"https:\/\/blog.cobwebgames.com\/wp-content\/uploads\/2026\/10\/Optimizing-Unity-Games-for-Mobile.webp","datePublished":"2026-10-10T00:13:29+00:00","author":{"@id":"https:\/\/blog.cobwebgames.com\/#\/schema\/person\/8f8a3c56d95587bfb360f183ab46e7bb"},"description":"A field manual for Unity mobile optimization: profile on device, cut draw calls, fix memory and GC spikes, and hold a stable frame rate without overheating.","breadcrumb":{"@id":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware#primaryimage","url":"https:\/\/blog.cobwebgames.com\/wp-content\/uploads\/2026\/10\/Optimizing-Unity-Games-for-Mobile.webp","contentUrl":"https:\/\/blog.cobwebgames.com\/wp-content\/uploads\/2026\/10\/Optimizing-Unity-Games-for-Mobile.webp","width":1672,"height":941,"caption":"Optimizing Unity Games for Mobile"},{"@type":"BreadcrumbList","@id":"https:\/\/blog.cobwebgames.com\/how-to-optimize-unity-games-for-mobile-hardware#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home \u00bb Blog","item":"https:\/\/blog.cobwebgames.com\/"},{"@type":"ListItem","position":2,"name":"How to Optimize Unity Games for Mobile Hardware?"}]},{"@type":"WebSite","@id":"https:\/\/blog.cobwebgames.com\/#website","url":"https:\/\/blog.cobwebgames.com\/","name":"Cobweb Games","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.cobwebgames.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.cobwebgames.com\/#\/schema\/person\/8f8a3c56d95587bfb360f183ab46e7bb","name":"Zain Khan","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/40dc17f49613f4641110ee6317c7bebfe4b4b23a544febb10f0aefc5d0e5a748?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/40dc17f49613f4641110ee6317c7bebfe4b4b23a544febb10f0aefc5d0e5a748?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/40dc17f49613f4641110ee6317c7bebfe4b4b23a544febb10f0aefc5d0e5a748?s=96&d=mm&r=g","caption":"Zain Khan"},"description":"Head of Cobweb Games Zain Khan leads Cobweb Games from the front, a San Francisco-based studio he built from an animation background into a full game development team, and one he still runs with a hand in the actual work, not just the organizational chart. Under his direction, the studio has grown into a single pipeline covering game design, character and environment art, cinematics, and mobile game development, work that recently earned Cobweb Games a 98 out of 100 Core Competencies score and a verified 5.0-star rating on GoodFirms. He stays close to every project because he believes the studios doing the best work are the ones where leadership never fully steps out of the room.","sameAs":["https:\/\/blog.cobwebgames.com"],"url":"https:\/\/blog.cobwebgames.com\/author\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.cobwebgames.com\/wp-json\/wp\/v2\/posts\/482","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.cobwebgames.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.cobwebgames.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.cobwebgames.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.cobwebgames.com\/wp-json\/wp\/v2\/comments?post=482"}],"version-history":[{"count":1,"href":"https:\/\/blog.cobwebgames.com\/wp-json\/wp\/v2\/posts\/482\/revisions"}],"predecessor-version":[{"id":484,"href":"https:\/\/blog.cobwebgames.com\/wp-json\/wp\/v2\/posts\/482\/revisions\/484"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.cobwebgames.com\/wp-json\/wp\/v2\/media\/483"}],"wp:attachment":[{"href":"https:\/\/blog.cobwebgames.com\/wp-json\/wp\/v2\/media?parent=482"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.cobwebgames.com\/wp-json\/wp\/v2\/categories?post=482"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.cobwebgames.com\/wp-json\/wp\/v2\/tags?post=482"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}