Ako spraviť LOD pre tisíce animovaných postáv v Unity
Návod na LOD pre dav v Unity s vertex animation textures: prečo rozhodujú vrcholy, nie trojuholníky, LOD ako nová sieť a výber úrovne po entitách.

LOD pre tisíce animovaných postáv v Unity postavte podľa počtu vrcholov, nie trojuholníkov: pri vertex animation textures sa animácia počíta na každý vrchol. Nižšie úrovne pripravte ručne, vrcholy najnižšej úrovne pripojte k povrchu originálu a úroveň vyberajte pre každú postavu zvlášť. V našej tower defense hre pre PC to pri 3 000 nepriateľoch zvýšilo FPS pri zábere do davu z 62 na 120.
Postup sa týka hier, kde sa na obrazovke pohybujú tisíce postáv naraz, teda tower defense, stratégií a survival hier. Naša hra je postavená v Unity s ECS a nájdete ju v referenciách. LOD znamená level of detail: vzdialená postava sa kreslí z jednoduchšej siete. Obrázky sú skutočné siete nášho nepriateľa kostry, nie zábery z hry.
Prečo generovaný LOD pri dave nepomôže
Unity vie úrovne LOD vygenerovať pri importe modelu (funkcia Mesh LOD). Pre tisíce postáv to má dva problémy.
Prvý je vzhľad. Automatické zjednodušenie trhalo tenké končatiny a rozbíjalo UV, teda mapovanie textúry na sieť.
Druhý je cena animácie. Štandardné kostrové animácie sú pre tisíce entít príliš drahé, preto sa namiesto nich používajú vertex animation textures (VAT). VAT je textúra, kde každý stĺpec patrí jednému vrcholu a každý riadok jednej snímke animácie. Shader si polohu vrcholu prečíta z textúry, takže cena animácie závisí od počtu čítaných vrcholov, a to aj pri kreslení tieňov.
Hornú hranicu ukazuje test s vynútenou generovanou úrovňou na všetkých postavách (Unity vygeneruje aj úrovne 3 a 4, build, 1080p, 3 000 nepriateľov, tiene zapnuté):
| Vynútená úroveň | Trojuholníky | FPS |
|---|---|---|
| LOD 0 | 11 miliónov | 72 |
| LOD 1 | 6 miliónov | 96 |
| LOD 2 | 3,68 milióna | 120 |
| LOD 4 | 1,43 milióna | 201 |
Priestor na zrýchlenie je veľký. Treba ho získať bez viditeľných dier a skokov medzi úrovňami.
Počítajte vrcholy, nie trojuholníky
Polovičný počet trojuholníkov sám osebe nepomôže. LOD s polovicou trojuholníkov a 996 z pôvodných 1 521 vrcholov ušetril 1,9 ms na snímku, LOD s 217 vrcholmi 6,4 ms. Pri každej úrovni sledujte oba počty.
Vrcholov býva zbytočne veľa. Vrchol sa zdvojí na každom šve UV, lebo jedna poloha potom potrebuje dve súradnice textúry. Naše modely z AI generátora mali UV rozsekané na stovky ostrovov: kostra mala 1 521 vrcholov, ale len 608 rôznych kombinácií polohy a normály.
Krok 1: Znížte vrcholy v LOD 0
Prvá úspora nestojí žiadny detail. Spojte vrcholy so zhodnou polohou a podobnou normálou (rozdiel do 25°), rozbaľte UV nanovo so švami len na ostrých hranách (nad 70°) a textúru prepočítajte z pôvodnej po trojuholníkoch. Kostra klesla z 1 521 na 1 090 vrcholov, u ostatných typov nepriateľov to bolo o 19 až 29 % menej, pri rovnakom tvare.
Do VAT potom zapisujte len stĺpce vrcholov, ktoré niektorá úroveň skutočne používa. Ušetrilo to 40 až 60 % pamäte animácií.
Krok 2: LOD 1 zo zjednodušenia a so zdieľanou textúrou
LOD 1 je zjednodušený LOD 0 na približne 52 % trojuholníkov. Zjednodušujte po kúskoch (každá kombinácia kosti a súvislej časti siete) a vrcholy na hraniciach kúskov zamknite. Hlave dajte väčší rozpočet, lebo silueta hlavy je to, čo oko v dave rozozná.
Dôležité je ponechať textúru LOD 0. Úroveň s vlastnou textúrou alebo iným tvarom je pri prechode viditeľná aj pri podobnej siluete.
Pod zhruba 50 % trojuholníkov zjednodušenie z existujúcich vrcholov trhá tenké časti a samostatné kúsky. Nižšie treba ísť inak.

Krok 3: LOD 2 ako nová sieť pripojená k originálu
Najnižšia úroveň je nová uzavretá sieť. Originálu pridajte vrstvu hrúbky, spravte voxel remesh a zjednodušte na cieľový počet (u nás 200 až 460 trojuholníkov podľa typu nepriateľa). Výslednú sieť oblepte na povrch originálu a UV spravte automaticky. Textúru zapečte z originálu v rovnakej hustote ako LOD 0, aby sedeli aj mipmapy.
Nová sieť nemá váhy animácie. Každý jej vrchol preto pripojte k najbližšiemu trojuholníku originálu. Uložte si tri stĺpce toho trojuholníka a barycentrické váhy (podiely, ktoré určujú polohu bodu v trojuholníku).

Stĺpec pripojeného vrcholu vo VAT je vážený súčet polôh a normál tých troch vrcholov v každej snímke. Shader nič nerieši, pripojený vrchol je obyčajný ďalší stĺpec.
pre každú snímku f:
VAT[pripojený, f] = w0 * VAT[a, f] + w1 * VAT[b, f] + w2 * VAT[c, f]
Krok 4: Diery kontrolujte strojom
Obrázky z modelovacieho nástroja diery spoľahlivo neukážu. Kontrola stačí jednoduchá: vykreslite originál a kandidáta z 11 smerov v rozlíšení 120 px a porovnajte siluety.
Za dieru počítajte pixely originálu vo vnútri obrysu kandidáta, ktoré kandidát nepokryje, a pixely kandidáta viac ako 2 px mimo obrysu originálu. U nás je limit 1 % dier a 4 až 6 % straty. Kontrola musí rešpektovať odstraňovanie zadných stien podľa materiálu. Limity sme nastavili podľa toho, kde boli prechody v hre okom viditeľné.
Krok 5: Vyberajte úroveň pre každú postavu zvlášť
Prepínanie úrovne pre celú mapu naraz je viditeľné. Keď vyberáte po entitách, prechody sa rozložia a v dave zaniknú.


Upozornenie k verzii: dokumentácia Unity 6.2 uvádza, že Entities Graphics vždy používa LOD 0. Výber po entitách podľa vzorca nižšie používame v Unity 6.6, pred nasadením si overte správanie vašej verzie:
LOD = log2(d * C / D) * sklon + posun
C = prah * 2 * tan(fov / 2) / vyska_obrazu
Tu je d vzdialenosť od kamery a D priemer svetových hraníc entity. Sklon a posun zvoľte tak, aby úroveň 1 začínala pri 93,3 a úroveň 2 pri 167,9 metra (kamera s fov 30° a 1440 px). Globálny prah LOD nastavte na výšku obrazu / 1440, potom vzdialenosti nezávisia od rozlíšenia.
Dve chyby, na ktoré si dajte pozor:
- Mierka. Priemer
Dpočítajte zo svetových hraníc, teda s mierkou prefabu. Siete pre VAT bývajú v malých jednotkách a prefab ich zväčší 2-krát až 4-krát. Bez toho vám hra celý čas kreslí LOD 0 a nič to nehlási. Správnosť overte počtom trojuholníkov v bežnom režime oproti vynútenému LOD. Pootočenie entity zväčšuje osovo zarovnané hranice, preto u nás priemer násobíme koeficientom 1,22. - Bakovanie. Krivka výberu sa zapeká pri bakovaní SubScene a zmenu v sieti bakovanie nezachytí. Po jej úprave vynúťte nové bakovanie SubScene.
Výsledky a limity
Build pre macOS, 2560 × 1440, 3 000 nepriateľov, tiene zapnuté, hra zastavená po prehre (animácie VAT stále bežia, takže meranie platí pre grafiku):
| Scéna | Pred | Po |
|---|---|---|
| Celá mapa | 90 FPS | 130 FPS |
| Priblíženie do davu | 62 FPS | 120 FPS |
Na Steam Decku (1280 × 800, 8 výpočtových jednotiek RDNA 2) je to 75 až 80 FPS na celej mape. Najbližší záber do davu má pri vysokej kvalite tieňov 33 FPS, bez tieňov 64. Tiene sú teda najväčšia zostávajúca položka: LOD znižuje aj ich cenu, ale vypnutie stále spraví veľký skok.
Čo LOD nerieši: kontrola dier beží v T-póze, takže natiahnutie siete v extrémnych pózach neodhalí. Jeden typ nepriateľa ešte limit dier v LOD 2 presahuje. Výpočet pohybu hordy LOD neovplyvní, ten rieši článok o navigácii hordy v Unity DOTS a reakcie na výbuchy fake ragdoll.
Potrebujete pomôcť s výkonom hry v Unity alebo simuláciou davu? Napíšte nám.


