In dit bericht kijken we naar het gebruik van Packed Level Actors voor Unreal Engine om de prestaties te verbeteren bij het renderen van meerdere instanties van een mesh.
Het is cruciaal om efficiënt om te gaan met de beperkte beschikbare resources bij het ontwikkelen voor VR/MR-headsets, die vrij beperkte hardware hebben. Bijvoorbeeld, Meta vermeldt voorbeeldbereiken van 200 - 1000 draw-calls en 1,3 m - 1,8 m driehoeken voor een Quest 3/3s, afhankelijk van het CPU-gebruik van de applicatie.
Tech Stack
Voor deze verkenning gebruiken we de volgende tech stack:
Packed Level Actors
Een Packed Level Actor aggregeert geselecteerde meshes/actors in een enkel Level/Blueprint met behulp van Instanced Static Mesh Components, zie Unreal Engine documentatie voor details over het maken van een Packed Level Actor.
Het hoofddoel is om de prestaties te optimaliseren (door het gebruik van Instanced Static Mesh Components, die een enkele draw-call gebruiken, zelfs bij het renderen van meerdere instanties van hetzelfde mesh per materiaal), en mogelijk het handiger maken om bepaalde mesh-composities meerdere keren in een level te plaatsen.
Meerdere Packed Level Actor instanties in een enkel level
Na enige tests blijkt dat Unreal Engine meerdere instanties van een Packed Level Actor niet automatisch aggregeert wanneer ze in een level worden geplaatst, wat de prestaties zou verbeteren door de benodigde draw-calls te verminderen.
We hebben het volgende testscenario gebruikt:
- Een Packed Level Actor met een enkele Instanced Static Mesh Component met 1 instantie voor een gebouwsegment van ongeveer 1,8k driehoeken met 4 LODs
- Deze Packed Level Actor 550 keer in een level plaatsen
- We observeren het aantal draw-calls en gerenderde driehoeken in het level met behulp van het
stat unitdebug-tool (DrawsenPrimswaarden)
Het resultaat is te zien in de volgende afbeelding.

Het resultaat is vrij slecht, gezien het feit dat elke Packed Level Actor-instantie resulteert in 1 draw-call. Ten minste worden de juiste LODs gebruikt voor elke instantie, waardoor het aantal gerenderde driehoeken aanzienlijk wordt verminderd, duidelijk onder het maximum van 990k.
Samenvoegen van meerdere Packed Level Actor instanties in een enkel level
In een poging om deze situatie te verbeteren, hebben we een Blueprint Actor gemaakt die identieke Packed Level Actor-instanties tijdens runtime samenvoegt, door de gebruikte mesh en materialen te vergelijken.
De Blueprint doet in principe het volgende:
- Itereer over alle Packed Level Actors in het level
- Itereer over elke Instanced Static Mesh Component in de Packed Level Actor (
source-component)- Als we al een andere Instanced Static Mesh Component hebben voor hetzelfde mesh/materialen, voeg alle instanties uit de
source-componenttoe aan deze component - Als we nog geen andere Instanced Static Mesh Component hebben voor hetzelfde mesh/materialen, gebruik de
source-componentvoor de volgende keer
- Als we al een andere Instanced Static Mesh Component hebben voor hetzelfde mesh/materialen, voeg alle instanties uit de
- Itereer over elke Instanced Static Mesh Component in de Packed Level Actor (
Het resultaat is te zien in de volgende afbeelding.

Het aantal draw-calls werd aanzienlijk verminderd (zoals verwacht), maar het aantal driehoeken is aanzienlijk toegenomen, wat vrij slecht is. De reden is dat de gebruikte Instanced Static Mesh Component het LOD selecteert voor de dichtstbijzijnde instantie en dit gebruikt om alle instanties te renderen, ongeacht hoe ver weg ze zijn.
Het belangrijkste nadeel van deze oplossing is dat het niet werkt met gebakken verlichting, omdat het resultaat er verschrikkelijk uit zal zien. Voor dynamisch gegenereerde levels met dynamische verlichting werkt het echter echt goed.
Bij gebruik van gebakken verlichting kunt u in plaats daarvan handmatig een Packed Level Actor maken die alle andere Packed Level Actors in het level bevat. Unreal Engine ondersteunt geneste Packed Level Actors en aggregeert alles correct in (Hierarchical) Instanced Static Meshes.
Gebruik van Hierarchical Instanced Static Mesh Components
In een poging om deze situatie te verbeteren, hebben we de Instanced Static Mesh Component in de Packed Level Actor Blueprint vervangen door een Hierarchical Instanced Static Mesh Component met dezelfde attributen. Dit voegt een lichte overhead toe, maar het zal het juiste LOD voor elke instantie kiezen, wat het aantal gerenderde driehoeken aanzienlijk kan verminderen, ten koste van enkele extra draw-calls.
Het resultaat is te zien in de volgende afbeelding.

Dit resultaat is vrij goed, gezien hoeveel meshes worden gerenderd.
Conclusie
Tijdens de ontwikkeling is het belangrijk om de prestaties te monitoren, vooral voor VR/MR gezien de beperkte beschikbare hardware. Door een Blueprint Actor te maken om identieke Packed Level Actors samen te voegen, en Hierarchical Instanced Static Mesh Components te gebruiken, kunnen we aanzienlijk meer en gedetailleerdere meshes in een level gebruiken, terwijl we de prestaties op acceptabele niveaus houden.
In dit voorbeeldscenario hebben we het aantal draw-calls verminderd van 559 naar 14, terwijl we nog steeds LODs overwegen om het aantal driehoeken rond 130k te houden, door een Blueprint Actor te maken die Packed Level Actor-instanties tijdens runtime samenvoegt, en Hierarchical Instanced Static Mesh Components te gebruiken.
| Scenario | Draw-calls | Driehoeken |
|---|---|---|
| 550 individuele Packed Level Actors | 559 | 130k |
| Samenvoegen van 550 Packed Level Actors met ISM | 10 | 995k |
| Samenvoegen van 550 Packed Level Actors met HISM | 14 | 127k |
Wij bij Immerstory zijn enthousiast om onze klanten te ondersteunen met hun immersieve ervaringen, en kijken ernaar uit om binnenkort meer verkenning voortgang te delen.
Welke immersieve ervaring zou je graag willen zien? Laat het ons weten!

