LOD készítése több ezer animált karakterhez Unityben

Útmutató tömeg LOD-hoz Unityben vertex animation textures használatával: miért a csúcsok számítanak, LOD új hálóként és entitásonkénti kiválasztás.

Ugyanannak a csontváz karakternek három változata balról jobbra csökkenő háromszögszámmal

A több ezer animált karakter LOD-ját Unityben a csúcsok száma alapján építse fel, ne a háromszögek szerint: vertex animation textures esetén az animációt csúcsonként kell kiszámítani. Az alsóbb szinteket készítse el kézzel, a legalsó szint csúcsait kösse az eredeti felületéhez, a szintet pedig karakterenként válassza ki. PC-s tower defense játékunkban ez 3 000 ellenfélnél a tömegbe közelítve 62-ről 120-ra emelte az FPS-t.

Az eljárás azokra a játékokra vonatkozik, ahol egyszerre több ezer karakter mozog a képernyőn: tower defense, stratégiai és survival játékokra. A miénk Unityben, ECS-sel készül, és a referenciák között található. A LOD a level of detail rövidítése: a távoli karaktert egyszerűbb hálóból rajzoljuk. A képek csontváz ellenfelünk valódi hálóit mutatják, nem játékbeli felvételek.

Miért nem segít a generált LOD egy tömegnél

A Unity a modell importálásakor képes LOD szinteket generálni (a Mesh LOD funkció). Több ezer karakternél ennek két gondja van.

Az első a kinézet. Az automatikus egyszerűsítés felszakította a vékony végtagokat és elrontotta az UV-t, vagyis a textúra leképezését a hálóra.

A második az animáció ára. A hagyományos csontvázas animáció több ezer entitásnál túl drága, ezért vertex animation textures (VAT) kerül a helyére. A VAT olyan textúra, amelyben minden oszlop egy csúcshoz, minden sor egy animációs képkockához tartozik. A shader a textúrából olvassa ki a csúcs helyzetét, így az animáció ára a kiolvasott csúcsok számától függ, az árnyékok rajzolásakor is.

A plafont egy teszt mutatja, ahol minden karakterre egy generált szintet kényszerítettünk (a Unity a 3. és 4. szintet is előállítja, build, 1080p, 3 000 ellenfél, bekapcsolt árnyékok):

Kényszerített szint Háromszögek FPS
LOD 0 11 millió 72
LOD 1 6 millió 96
LOD 2 3,68 millió 120
LOD 4 1,43 millió 201

A gyorsításra bőven van tér. Ezt látható lyukak és a szintek közti ugrások nélkül kell kihasználni.

A csúcsokat számolja, ne a háromszögeket

A fele annyi háromszög önmagában nem segít. Egy LOD fele annyi háromszöggel és az eredeti 1 521 csúcsból 996-tal 1,9 ms-ot takarított meg képkockánként, egy 217 csúcsos LOD 6,4 ms-ot. Minden szintnél kövesse mindkét számot.

Gyakran fölöslegesen sok a csúcs. Minden UV-varratnál megkettőződik a csúcs, mert egy pozícióhoz ilyenkor két textúrakoordináta tartozik. Az AI-generátorból származó modelljeink UV-ja több száz szigetre volt vágva: a csontváznak 1 521 csúcsa volt, de csak 608 különböző pozíció-normál párosa.

1. lépés: Csökkentse a csúcsokat a LOD 0-ban

Az első megtakarítás nem jár részletvesztéssel. Egyesítse az azonos pozíciójú és hasonló normálú csúcsokat (25° eltérésig), bontsa ki újra az UV-t csak az éles éleken (70° felett) varrattal, és a textúrát számolja át a régiből háromszögenként. A csontváz 1 521-ről 1 090 csúcsra csökkent, a többi ellenféltípus 19-29 %-kal, változatlan alakkal.

Ezután csak azoknak a csúcsoknak az oszlopait írja a VAT-ba, amelyeket valamelyik szint ténylegesen használ. Ez az animációs memória 40-60 %-át spórolta meg.

2. lépés: LOD 1 egyszerűsítéssel, közös textúrával

A LOD 1 a háromszögek körülbelül 52 %-ára egyszerűsített LOD 0. Darabonként egyszerűsítsen (a csont és a háló összefüggő részének minden párosítása), és rögzítse a darabok határán lévő csúcsokat. A fejnek adjon nagyobb keretet, mert a fej sziluettjét ismeri fel a szem a tömegben.

Fontos megtartani a LOD 0 textúráját. Az önálló textúrájú vagy más alakú szint átmenetkor hasonló sziluett mellett is látszik.

A háromszögek nagyjából 50 %-a alatt a meglévő csúcsokból való egyszerűsítés felszakítja a vékony részeket és a különálló darabokat. Lejjebb másképp kell haladni.

A csontváz karakter három változata egymás mellett, csökkenő háromszögszámmal
Ugyanaz a csontváz három szinten: 873, 448 és 330 háromszög, 1 090, 705 és 520 csúcs.

3. lépés: LOD 2 az eredetihez kötött új hálóként

A legalsó szint új, zárt háló. Vastagítsa meg az eredetit egy réteggel, futtasson voxel remesht, és egyszerűsítsen a célszámra (nálunk ellenféltípustól függően 200-460 háromszög). Az eredményt húzza rá az eredeti felületére, az UV-t pedig készítse automatikusan. A textúrát az eredetiből süsse a LOD 0-val azonos sűrűségben, hogy a mipmapek is egyezzenek.

Az új hálónak nincsenek animációs súlyai. Ezért minden csúcsát kösse az eredeti legközelebbi háromszögéhez. Mentse el a háromszög három oszlopát és a baricentrikus súlyokat (az arányokat, amelyek meghatározzák a pont helyét a háromszögön belül).

Vázlat: az egyszerűsített háló piros csúcsa szaggatott vonalakkal kapcsolódik az eredeti háromszög három csúcsához
Az alsóbb szint csúcsa (piros) a legközelebbi eredeti háromszög három csúcsával együtt mozog.

A kötött csúcs VAT-oszlopa minden képkockában a három csúcs pozíciójának és normáljának súlyozott összege. A shadernek semmi különöset nem kell tennie, a kötött csúcs csak egy újabb oszlop.

minden f képkockára:
    VAT[kötött, f] = w0 * VAT[a, f] + w1 * VAT[b, f] + w2 * VAT[c, f]

4. lépés: Géppel ellenőrizze a lyukakat

A modellező eszköz képei nem mutatják megbízhatóan a lyukakat. Elég egy egyszerű ellenőrzés: renderelje az eredetit és a jelöltet 11 irányból 120 px-es felbontásban, és hasonlítsa össze a sziluetteket.

Lyuknak számítsanak az eredeti pixelei a jelölt körvonalán belül, amelyeket a jelölt nem fed le, valamint a jelölt pixelei az eredeti körvonalán több mint 2 px-lel kívül. Nálunk a határ 1 % lyuk és 4-6 % veszteség. Az ellenőrzésnek figyelembe kell vennie az anyagtól függő hátlap-eltávolítást. A határokat az alapján állítottuk be, hogy hol látszottak az átmenetek a játékban.

5. lépés: Karakterenként válasszon szintet

Ha az egész térképen egyszerre vált a szint, az látszik. Entitásonkénti kiválasztásnál az átmenetek eloszlanak és eltűnnek a tömegben.

Egész térkép egyszerreEgyszínű pontok tömege, minden karakter ugyanazon a szinten
EntitásonkéntPontok tömege a kamerától mért távolság szerinti sávokban, közel piros, távol szürke
Felülnézet, a kamera alul. A szín a LOD szint: piros 0, narancs 1, szürke 2.

Verziófigyelmeztetés: a Unity 6.2 dokumentációja szerint az Entities Graphics mindig LOD 0-t használ. Az alábbi képlet szerinti entitásonkénti kiválasztást Unity 6.6-ban használjuk, ezért előbb ellenőrizze a saját verziója viselkedését:

LOD = log2(d * C / D) * meredekseg + eltolas
C = kuszob * 2 * tan(fov / 2) / kepmagassag

Itt d a kamerától mért távolság, D pedig az entitás világbeli határainak átmérője. A meredekséget és az eltolást úgy válassza meg, hogy az 1. szint 93,3, a 2. szint 167,9 méternél kezdődjön (30°-os fov és 1440 px-es kamera). A globális LOD-küszöböt állítsa képmagasság / 1440 értékre, így a távolságok nem függenek a felbontástól.

Két hiba, amelyre figyeljen:

  • Méretarány. A D átmérőt a világbeli határokból számolja, tehát a prefab méretarányával együtt. A VAT-hálók gyakran kis egységekben vannak, a prefab 2-4-szeresére nagyítja őket. Enélkül a játék végig LOD 0-t rajzol, és nem jelez semmit. Ellenőrizze a háromszögek számával normál módban egy kényszerített LOD-hoz képest. Az entitás elforgatása megnöveli a tengelyhez igazított határokat, ezért nálunk az átmérőt 1,22-es szorzóval számoljuk.
  • Sütés. A kiválasztási görbe a SubScene sütésekor kerül rögzítésre, és a sütés nem veszi észre a háló változását. Módosítás után kényszerítse ki a SubScene újrasütését.

Eredmények és korlátok

macOS build, 2560 × 1440, 3 000 ellenfél, bekapcsolt árnyékok, a játék game over után megállítva (a VAT-animációk továbbra is futnak, így a mérés a grafikára érvényes):

Jelenet Előtte Utána
Teljes térkép 90 FPS 130 FPS
Közelítés a tömegbe 62 FPS 120 FPS

A Steam Decken (1280 × 800, 8 RDNA 2 számítási egység) ez 75-80 FPS a teljes térképen. A tömeghez legközelebbi nézet magas árnyékminőséggel 33 FPS, árnyékok nélkül 64. Az árnyékok jelentik tehát a legnagyobb megmaradt költséget: a LOD ezek árát is csökkenti, de a kikapcsolásuk még mindig nagy ugrást ad.

Amit a LOD nem old meg: a lyukellenőrzés T-pózban fut, így nem veszi észre az extrém pózokban fellépő nyúlást. Egy ellenféltípus LOD 2-ben még túllépi a lyukhatárt. A horda mozgásának számítására a LOD nincs hatással, erről a horda navigációja Unity DOTS-ban cikk szól, a robbanásokra adott reakciókról pedig a fake ragdoll.

Segítségre van szüksége Unity-játéka teljesítményével vagy tömegszimulációval kapcsolatban? Írjon nekünk.

← Továbbiak: Tower Defense