Розроблення системи частинок та VFX для мобільних ігор
Система частинок на мобілі — це постійний компроміс між візуальною якістю та бюджетом GPU. Десктопний ефект з 50 000 частинок на iPhone 11 призведе до перегріву та падіння до 20 FPS. Завдання — знайти точку рівноваги, де ефекти виглядають переконливо з 10 000 частинок або менше.
Вибір інструменту: Unity vs SpriteKit vs Metal
Більшість мобільних ігор використовують один із трьох: Unity Particle System (Shuriken), Apple SpriteKit SKEmitterNode, або користувацькі системи на Metal/OpenGL ES/Vulkan для особливих вимог.
Unity Shuriken є фактичним стандартом. Візуальний редактор, підтримка Sub Emitters, GPU Instancing, компілятор Burst для CPU-симуляції. VFX Graph (GPU-симуляція через Compute Shaders) працює на мобілі починаючи з Metal (iOS 12+) та Vulkan (Android API 24+). На старіших пристроях VFX Graph недоступний — необхідний fallback на Shuriken.
SpriteKit SKEmitterNode — рідний для iOS для 2D-ігор. Простий, швидкий, без overhead Unity. Але обмежений: немає Sub Emitters, немає користувацьких шейдерів без Metal. Для простих ефектів (вогонь, дощ, конфеті) достатньо.
Бюджет частинок та обмеження GPU
На мобільних GPU (Apple A-series, Adreno, Mali) вузькі місця часто не в кількості частинок, а в overdraw — кількості разів, коли кожен пиксель екрану перерисовується за кадр.
Напівпрозорі частинки з адитивним змішуванням (Additive shader mode) спричиняють overdraw пропорційно кількості шарів. На вибуху з 5000 частинок у центрі екрану реальний overdraw може бути 50–100x. Це гублить fill rate навіть на A15.
Стратегії оптимізації:
- Texture Atlasing: усі спрайти частинок в одному атласі 512×512 або 1024×1024. Зменшує draw calls при зміні текстури
- Billboard imposters: для об'ємних ефектів (хмара вибуху) — quad із запечена текстурою замість сотень сфер
-
LOD для частинок: на відстані / при низькому fps — зменшити
maxParticlesвдвічі черезQualitySettings.particleRaycastBudgetабо користувацький LOD-менеджер
// Unity: динамічний LOD системи частинок за FPS
public class ParticleLODManager : MonoBehaviour {
[SerializeField] private ParticleSystem targetSystem;
private ParticleSystem.MainModule _main;
private float _fpsTimer;
void Start() {
_main = targetSystem.main;
}
void Update() {
_fpsTimer += Time.deltaTime;
if (_fpsTimer < 1f) return;
_fpsTimer = 0;
float fps = 1f / Time.smoothDeltaTime;
if (fps < 45f) {
_main.maxParticles = Mathf.Max(100, _main.maxParticles / 2);
} else if (fps > 58f && _main.maxParticles < originalMax) {
_main.maxParticles = Mathf.Min(originalMax, _main.maxParticles * 2);
}
}
}
Користувацькі шейдери для мобільного VFX
Вбудовані шейдери Unity для частинок (Particles/Standard Unlit) безпечні, але обмежені. Для ефектів розчинення, спотворення тепла, енергетичних щитів — необхідні користувацькі шейдери.
На мобілі правила жорсткі: немає discard у шейдері (ранній Z-test ламається, fill rate падає), мінімум texture samples, уникайте залежних texture reads. Shader Model 2.0 як baseline для широкого охопленого.
Приклад простого ефекту спотворення для вибухів (Unity HLSL):
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _NoiseTex;
float _DistortionStrength;
float _FadeEdges;
fixed4 frag (v2f i) : SV_Target {
float2 noise = tex2D(_NoiseTex, i.uv + _Time.y * 0.3).rg * 2 - 1;
float2 distortedUV = i.uv + noise * _DistortionStrength * i.color.a;
float edge = 1 - saturate(distance(distortedUV, float2(0.5, 0.5)) * _FadeEdges);
fixed4 col = tex2D(_MainTex, distortedUV) * i.color;
col.a *= edge;
return col;
}
ENDCG
i.color.a — це альфа частинки з Unity Particle System, синхронізується з часом життя. Спотворення затухає разом з частинкою автоматично.
Ефекти SpriteKit: вогонь та конфеті
SKEmitterNode налаштовується або в редакторі Xcode (.sks файл), або програмно. Програмно — переважно для динамічних параметрів:
func makeFireEmitter() -> SKEmitterNode {
let emitter = SKEmitterNode()
emitter.particleTexture = SKTexture(imageNamed: "spark")
emitter.particleBirthRate = 120
emitter.particleLifetime = 1.2
emitter.particleLifetimeRange = 0.4
emitter.particleSpeed = 80
emitter.particleSpeedRange = 40
emitter.emissionAngle = .pi / 2 // вгору
emitter.emissionAngleRange = .pi / 8
emitter.particleScale = 0.15
emitter.particleScaleSpeed = -0.1
emitter.particleAlphaSpeed = -0.8
emitter.particleColorSequence = SKKeyframeSequence(
keyframeValues: [SKColor.yellow, SKColor.orange, SKColor.red, SKColor.clear],
times: [0, 0.3, 0.7, 1.0]
)
emitter.particleBlendMode = .add
return emitter
}
.add blending — адитивне змішування. Вогонь та іскри виглядають світлячими. Не використовуйте для диму та пилу — там потрібен .alpha.
Інструменти профілювання GPU
Xcode Metal Debugger — перехоплення кадру для Metal-ігор. Див. кожен draw call, текстури, візуалізацію overdraw. Для Unity на iOS: через Xcode GPU Frame Debugger при підключенні через USB.
Android GPU Inspector (AGI) — від Google для Adreno та Mali. Frame Profiler показує етапи pipeline, де GPU чекає.
Unity Profiler — вбудований, показує час CPU/GPU для рендеру кожного ефекту. Якщо Rendering → ParticleSystem.Update перевищує 2ms, перевірте CPU-симуляцію та зменшіть maxParticles або переключіться на GPU Mode.
Робочий процес
Технічний art direction: які ефекти потрібні, їх частота на екрані одночасно, цільові пристрої. Розроблення шейдерів та систем частинок у редакторі з профілюванням на слабких Android-пристроях. Налаштування LOD-системи. Інтеграція в ігровий movimento, тест теплових throttling (10-хвилинна ігрова сесія з моніторингом температури).
Оцінка часу
3–5 робочих днів для базового набору VFX (3–5 типів ефектів). Складна користувацька система з Metal Compute Shaders — від 2 тижнів.







