Prestatieaanbeveling voor Unity

Dit artikel bouwt voort op de prestatieaanbeveling voor mixed reality, maar richt zich op verbeteringen die specifiek zijn voor Unity.

We hebben onlangs een toepassing uitgebracht met de naam Basisprincipes van kwaliteit, die veelvoorkomende problemen met prestaties, ontwerpen en omgevingen en oplossingen voor HoloLens 2-apps behandelt. Deze app is een geweldige visuele demo voor de inhoud die volgt.

De belangrijkste eerste stap bij het optimaliseren van de prestaties van mixed reality-apps in Unity is ervoor te zorgen dat u de aanbevolen omgevingsinstellingen voor Unity gebruikt. Dat artikel bevat inhoud met enkele van de belangrijkste scèneconfiguraties voor het bouwen van krachtige Mixed Reality-apps. Enkele van deze aanbevolen instellingen worden hieronder ook gemarkeerd.

Profilen met Unity

Unity biedt de ingebouwde Unity Profiler . Dit is een uitstekende resource voor het verzamelen van waardevolle prestatie-inzichten voor uw specifieke app. Hoewel u de profiler in de editor kunt uitvoeren, vertegenwoordigen deze metrische gegevens niet de echte runtime-omgeving, dus de resultaten moeten voorzichtig worden gebruikt. We raden u aan uw toepassing op afstand te profilen terwijl u op het apparaat wordt uitgevoerd voor de meest nauwkeurige en bruikbare inzichten.

Unity biedt geweldige documentatie voor:

  1. De Unity-profiler op afstand verbinden met UWP-toepassingen
  2. Prestatieproblemen effectief diagnosticeren met de Unity Profiler

GPU-profilering

Unity Profiler

Als de Unity Profiler is verbonden en nadat u de GPU-profiler hebt toegevoegd (zie Profiler toevoegen in de rechterbovenhoek), kunt u zien hoeveel tijd wordt besteed aan respectievelijk de CPU & GPU in het midden van de profiler. Hierdoor kan de ontwikkelaar een snelle benadering krijgen als de toepassing CPU- of GPU-gebonden is.

Unity CPU versus GPU

Notitie

Als u GPU-profilering wilt gebruiken, moet u Grafische taken uitschakelen in de Instellingen voor Unity Player. Zie De module GPU Usage Profiler van Unity voor meer informatie.

Foutopsporingsprogramma voor Unity-frame

Het Frame Debugger van Unity is ook een krachtig en inzichtelijk hulpprogramma om te gebruiken. Het geeft u een goed overzicht van wat de GPU doet elk frame. Waar u op moet letten, zijn extra renderingdoelen en blit-opdrachten om ertussen te kopiëren, omdat deze erg duur zijn op HoloLens. In het ideale geval mogen er geen doelen voor weergave buiten het scherm worden gebruikt op HoloLens. Deze worden meestal toegevoegd bij het inschakelen van dure renderingfuncties (bijvoorbeeld MSAA, HDR of effecten op volledig scherm zoals bloei) die moeten worden vermeden.

HoloLens-framesnelheid-overlay

De pagina Systeemprestaties van de apparaatportal bevat een goed overzicht van de CPU- en GPU-prestaties van het apparaat. U kunt Teller voor framesnelheid weergeven inschakelen in headset en Grafiek met de framesnelheid weergeven in de headset. Met deze opties wordt respectievelijk een FPS-teller en grafiek ingeschakeld die u onmiddellijk feedback geven in elke actieve toepassing op uw apparaat.

PIX

PIX kan ook worden gebruikt om Unity-toepassingen te profileren. Er zijn ook gedetailleerde instructies voor het gebruik en installeren van PIX voor HoloLens 2. In een ontwikkelbuild worden dezelfde bereiken die u ziet in het Frame Debugger van Unity ook weergegeven in PIX en kunnen ze in meer detail worden geïnspecteerd en geprofileerd.

Notitie

Unity biedt de mogelijkheid om de doelresolutie van uw toepassing tijdens runtime eenvoudig te wijzigen via de eigenschap XRSettings.renderViewportScale . De uiteindelijke afbeelding die op het apparaat wordt weergegeven, heeft een vaste resolutie. Het platform bemonstert de uitvoer met een lagere resolutie om een afbeelding met een hogere resolutie te maken voor weergave op beeldschermen.

UnityEngine.XR.XRSettings.renderViewportScale = 0.7f;

Aanbevelingen voor CPU-prestaties

De onderstaande inhoud bevat gedetailleerdere prestatieprocedures, met name gericht op Unity & C#-ontwikkeling.

Cacheverwijzingen

We raden u aan om verwijzingen naar alle relevante onderdelen en GameObjects tijdens de initialisatie in de cache op te slaan, omdat herhalende functieaanroepen, zoals GetComponent<T>() en Camera.main , duurder zijn ten opzichte van de geheugenkosten voor het opslaan van een aanwijzer. . Camera.main maakt alleen gebruik van FindGameObjectsWithTag() under, waarmee uw scènegrafiek op dure wijze wordt gezocht naar een cameraobject met de tag 'MainCamera' .

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour
{
    private Camera cam;
    private CustomComponent comp;

    void Start() 
    {
        cam = Camera.main;
        comp = GetComponent<CustomComponent>();
    }

    void Update()
    {
        // Good
        this.transform.position = cam.transform.position + cam.transform.forward * 10.0f;

        // Bad
        this.transform.position = Camera.main.transform.position + Camera.main.transform.forward * 10.0f;

        // Good
        comp.DoSomethingAwesome();

        // Bad
        GetComponent<CustomComponent>().DoSomethingAwesome();
    }
}

Notitie

GetComponent(tekenreeks) vermijden
Wanneer u GetComponent() gebruikt, zijn er een aantal verschillende overbelastingen. Het is belangrijk om altijd de op type gebaseerde implementaties te gebruiken en nooit de op tekenreeksen gebaseerde zoekoverbelasting. Zoeken op tekenreeks in uw scène is aanzienlijk duurder dan zoeken op Type.
(Goed) Component GetComponent(type)
(Goed) T GetComponent<T>()
(Slecht) Component GetComponent(tekenreeks)>

Vermijd dure bewerkingen

  1. Vermijd het gebruik van LINQ

    Hoewel LINQ overzichtelijk en gemakkelijk te lezen en te schrijven kan zijn, zijn er over het algemeen meer rekenkracht en geheugen nodig dan wanneer u het algoritme handmatig hebt geschreven.

    // Example Code
    using System.Linq;
    
    List<int> data = new List<int>();
    data.Any(x => x > 10);
    
    var result = from x in data
                 where x > 10
                 select x;
    
  2. Algemene Unity-API's

    Bepaalde Unity-API's kunnen, hoewel nuttig, duur zijn om uit te voeren. De meeste hiervan hebben betrekking op het doorzoeken van de hele scènegrafiek naar een overeenkomende lijst met GameObjects. Deze bewerkingen kunnen over het algemeen worden vermeden door verwijzingen in de cache te plaatsen of een manageronderdeel voor de GameObjects te implementeren om de verwijzingen tijdens runtime bij te houden.

        GameObject.SendMessage()
        GameObject.BroadcastMessage()
        UnityEngine.Object.Find()
        UnityEngine.Object.FindWithTag()
        UnityEngine.Object.FindObjectOfType()
        UnityEngine.Object.FindObjectsOfType()
        UnityEngine.Object.FindGameObjectsWithTag()
        UnityEngine.Object.FindGameObjectsWithTag()
    

Notitie

SendMessage() en BroadcastMessage() moeten ten koste van alles worden verwijderd. Deze functies kunnen 1000x langzamer zijn dan directe functieaanroepen.

  1. Pas op voor boksen

    Boksen is een kernconcept van de C#-taal en runtime. Het is het proces van het verpakken van variabelen met een waardetype, zoals char, int, bool, enzovoort, in variabelen met verwijzingstypen. Wanneer een waardetypevariabele 'boxed' is, wordt deze verpakt in een System.Object, die wordt opgeslagen op de beheerde heap. Er wordt geheugen toegewezen en uiteindelijk, wanneer het wordt verwijderd, moet worden verwerkt door de garbagecollector. Voor deze toewijzingen en deallocaties worden prestatiekosten in rekening gebracht en in veel scenario's zijn ze overbodig of kunnen ze eenvoudig worden vervangen door een goedkoper alternatief.

    Als u boksen wilt voorkomen, moet u ervoor zorgen dat de variabelen, velden en eigenschappen waarin u numerieke typen en structs (inclusief Nullable<T>) opslaat, sterk worden getypt als specifieke typen, zoals int, float? of MyStruct, in plaats van object te gebruiken. Als u deze objecten in een lijst opgeeft, moet u een sterk getypte lijst gebruiken, zoals List<int> in plaats List<object> van of ArrayList.

    Voorbeeld van boksen in C#

    // boolean value type is boxed into object boxedMyVar on the heap
    bool myVar = true;
    object boxedMyVar = myVar;
    

Herhalende codepaden

Herhalende Unity-callbackfuncties (bijvoorbeeld Update) die vaak per seconde en/of frame worden uitgevoerd, moeten zorgvuldig worden geschreven. Dure bewerkingen hebben een enorme en consistente invloed op de prestaties.

  1. Lege callbackfuncties

    Hoewel de onderstaande code onschuldig lijkt om in uw toepassing achter te laten, vooral omdat elk Unity-script automatisch wordt geïnitialiseerd met een Update-methode, kunnen deze lege callbacks duur worden. Unity werkt heen en weer tussen een grens van onbeheerde en beheerde code, tussen UnityEngine-code en uw toepassingscode. Contextoverschakeling via deze brug is vrij duur, zelfs als er niets is om uit te voeren. Dit wordt met name problematisch als uw app 100's GameObjects heeft met onderdelen met lege herhalende Unity-callbacks.

    void Update()
    {
    }
    

Notitie

Update() is de meest voorkomende manifestatie van dit prestatieprobleem, maar andere herhalende Unity-callbacks, zoals de volgende, kunnen even slecht zijn, zo niet erger: FixedUpdate(), LateUpdate(), OnPostRender", OnPreRender(), OnRenderImage(), enzovoort.

  1. Bewerkingen om één keer per frame te worden uitgevoerd

    De volgende Unity-API's zijn algemene bewerkingen voor veel Holografische apps. Hoewel dit niet altijd mogelijk is, kunnen de resultaten van deze functies meestal eenmaal worden berekend en de resultaten opnieuw worden gebruikt in de toepassing voor een bepaald frame.

    a) Het is een goede gewoonte om een speciale Singleton-klasse of -service te hebben om uw Blik raycast in de scène af te handelen en dit resultaat vervolgens opnieuw te gebruiken in alle andere scèneonderdelen, in plaats van herhaalde en identieke Raycast-bewerkingen voor elk onderdeel uit te voeren. Voor sommige toepassingen zijn mogelijk raycasts van verschillende origins of tegen verschillende LayerMasks vereist.

        UnityEngine.Physics.Raycast()
        UnityEngine.Physics.RaycastAll()
    

    b) Vermijd GetComponent() bewerkingen in herhaalde Unity-callbacks, zoals Update() door verwijzingen in Start() of Awake() op te cachen

        UnityEngine.Object.GetComponent()
    

    c) Het is een goede gewoonte om, indien mogelijk, alle objecten te instantiëren bij de initialisatie en objectgroepering te gebruiken om GameObjects te recyclen en opnieuw te gebruiken tijdens de runtime van uw toepassing

        UnityEngine.Object.Instantiate()
    
  2. Interfaces en virtuele constructies vermijden

    Het aanroepen van functie-aanroepen via interfaces versus directe objecten of het aanroepen van virtuele functies kan vaak veel duurder zijn dan het gebruik van directe constructies of directe functie-aanroepen. Als de virtuele functie of interface niet nodig is, moet deze worden verwijderd. De prestatietreffer voor deze benaderingen is echter de moeite waard als het gebruik ervan het samenwerken aan ontwikkeling, leesbaarheid van code en het onderhouden van code vereenvoudigt.

    Over het algemeen wordt aanbevolen om velden en functies niet als virtueel te markeren, tenzij er een duidelijke verwachting is dat dit lid moet worden overschreven. U moet vooral voorzichtig zijn met codepaden met een hoge frequentie die vaak per frame of zelfs eenmaal per frame worden aangeroepen, zoals een UpdateUI() methode.

  3. Vermijd het doorgeven van structs op waarde

    In tegenstelling tot klassen zijn structs waardetypen en wanneer ze rechtstreeks aan een functie worden doorgegeven, wordt de inhoud ervan gekopieerd naar een nieuw gemaakt exemplaar. Met deze kopie worden cpu-kosten en extra geheugen in de stack toegevoegd. Voor kleine structs is het effect minimaal en dus acceptabel. Voor functies die echter herhaaldelijk elk frame hebben aangeroepen, evenals functies die grote structs gebruiken, wijzigt u indien mogelijk de functiedefinitie om door verwijzing door te geven. Klik hier voor meer informatie

Diversen

  1. Natuurkunde

    a) Over het algemeen is de eenvoudigste manier om de fysica te verbeteren het beperken van de hoeveelheid tijd die is besteed aan fysica of het aantal iteraties per seconde. Dit vermindert de nauwkeurigheid van de simulatie. Zie TimeManager in Unity

    b) De typen colliders in Unity hebben sterk verschillende prestatiekenmerken. In de onderstaande volgorde worden de meest presterende en minst presterende colliers van links naar rechts vermeld. Het is belangrijk om Mesh Colliders te vermijden, die aanzienlijk duurder zijn dan de primitieve colliers.

    Sphere < Capsule < Box <<< Mesh (convex) < Mesh (niet-convex)

    Zie Aanbevolen procedures voor Unity Physics voor meer informatie

  2. Animaties

    Schakel niet-actieve animaties uit door het onderdeel Animator uit te schakelen (het uitschakelen van het gameobject heeft niet hetzelfde effect). Vermijd ontwerppatronen waarbij een animator zich in een lus bevindt waarbij een waarde op hetzelfde wordt ingesteld. Er is een aanzienlijke overhead voor deze techniek, zonder dat dit van invloed is op de toepassing. Klik hier voor meer informatie.

  3. Complexe algoritmen

    Als uw toepassing gebruikmaakt van complexe algoritmen zoals inverse kinematica, padzoeken, enzovoort, zoekt u een eenvoudigere benadering of past u relevante instellingen aan voor de prestaties

Aanbevelingen voor CPU-naar-GPU-prestaties

Over het algemeen zijn de prestaties van CPU-naar-GPU terug te voeren op de draw-aanroepen die naar de grafische kaart worden verzonden. Om de prestaties te verbeteren, moeten trekoproepen strategisch worden a) verminderd of b) worden geherstructureerd voor optimale resultaten. Omdat draw-aanroepen zelf resource-intensief zijn, vermindert het totale werk dat nodig is om ze te verminderen. Bovendien zijn statuswijzigingen tussen draw-aanroepen dure validatie- en vertaalstappen in het grafische stuurprogramma vereist. Daarom kan de herstructurering van de draw-aanroepen van uw toepassing om statuswijzigingen (d.w.z. verschillende materialen, enzovoort) te beperken, de prestaties verbeteren.

Unity heeft een geweldig artikel met een overzicht en een overzicht van batch-draw-oproepen voor hun platform.

Single Pass Instanced Rendering

Met Single Pass Instanced Rendering in Unity kunnen aanroepen voor elk oog worden teruggebracht tot één geïnsteerde draw-aanroep. Vanwege de cachecoherentie tussen twee draw-aanroepen, is er ook enige verbetering in de prestaties van de GPU.

Deze functie inschakelen in uw Unity-project

  1. Open OpenXR-instellingen (ga naarProjectinstellingen>bewerken>XR-invoegtoepassingsbeheer>OpenXR).
  2. Selecteer Single Pass Instanced in de vervolgkeuzelijst Render Mode .

Lees de volgende artikelen van Unity voor meer informatie over deze weergavemethode.

Notitie

Een veelvoorkomend probleem met Single Pass Instanced Rendering treedt op als ontwikkelaars al bestaande aangepaste shaders hebben die niet zijn geschreven voor instancing. Nadat deze functie is ingeschakeld, zien ontwikkelaars mogelijk dat sommige GameObjects slechts met één oog worden weergegeven. Dit komt doordat de bijbehorende aangepaste shaders niet de juiste eigenschappen voor instancing hebben.

Zie Single Pass Stereo Rendering voor HoloLens van Unity voor het oplossen van dit probleem

Statische batchverwerking

Unity kan veel statische objecten batches uitvoeren om het aantal aanroepen naar de GPU te verminderen. Statische batchverwerking werkt voor de meeste Renderer-objecten in Unity die 1) hetzelfde materiaal delen en 2) allemaal zijn gemarkeerd als Statisch (Selecteer een object in Unity en schakel het selectievakje in de rechterbovenhoek van de inspector in). GameObjects die zijn gemarkeerd als statisch , kunnen niet worden verplaatst tijdens de runtime van uw toepassing. Statische batchverwerking kan dus moeilijk te gebruiken zijn op HoloLens, waarbij vrijwel elk object moet worden geplaatst, verplaatst, geschaald, enzovoort. Voor immersive headsets kan statische batchverwerking het aantal oproepen tot tekenen aanzienlijk verminderen en zo de prestaties verbeteren.

Lees Statische batchverwerking onder Draw Call Batching in Unity voor meer informatie.

Dynamische batchverwerking

Omdat het problematisch is om objecten te markeren als statisch voor HoloLens-ontwikkeling, kan dynamische batchverwerking een geweldig hulpmiddel zijn om deze ontbrekende functie te compenseren. Het kan ook handig zijn voor immersive headsets. Dynamische batchverwerking in Unity kan echter moeilijk in te schakelen zijn omdat GameObjects a) hetzelfde materiaal moeten delen en b) voldoen aan een lange lijst met andere criteria.

Lees Dynamische batchverwerking onder Draw Call Batching in Unity voor de volledige lijst. Meestal worden GameObjects ongeldig om dynamisch batched te worden, omdat de gekoppelde mesh-gegevens niet meer dan 300 hoekpunten kunnen zijn.

Andere technieken

Batchverwerking kan alleen plaatsvinden als meerdere GameObjects hetzelfde materiaal kunnen delen. Normaal gesproken wordt dit geblokkeerd omdat GameObjects een unieke textuur moeten hebben voor hun respectieve materiaal. Het is gebruikelijk om texturen te combineren tot één grote textuur, een methode die ook wel Texture Atlasing wordt genoemd.

Bovendien verdient het de voorkeur om meshes waar mogelijk en redelijk te combineren in één GameObject. Elke Renderer in Unity heeft de bijbehorende draw-aanroep(en) versus het verzenden van een gecombineerde mesh onder één Renderer.

Notitie

Als u eigenschappen van Renderer.material tijdens runtime wijzigt, wordt er een kopie van het materiaal gemaakt en wordt batchverwerking mogelijk verbroken. Gebruik Renderer.sharedMaterial om eigenschappen van gedeeld materiaal in GameObjects te wijzigen.

Aanbevelingen voor GPU-prestaties

Meer informatie over het optimaliseren van grafische rendering in Unity

Bandbreedte en doorvoersnelheden

Bij het weergeven van een frame op de GPU is een toepassing afhankelijk van de geheugenbandbreedte of de vulsnelheid.

  • Geheugenbandbreedte is de snelheid van lees- en schrijfbewerkingen die de GPU kan uitvoeren vanuit het geheugen
  • De opvulsnelheid verwijst naar de pixels die per seconde door de GPU kunnen worden getekend.

Dieptebuffer delen optimaliseren

We raden u aan dieptebuffer delen in te schakelen om de stabiliteit van hologrammen te optimaliseren. Wanneer u met deze instelling op diepte gebaseerde herprojectie in een laat stadium inschakelt, raden we u aan een 16-bits diepteindeling te selecteren in plaats van een 24-bits diepteindeling . De 16-bits dieptebuffers verminderen de bandbreedte (en dus het vermogen) van dieptebufferverkeer drastisch. Dit kan een grote verbetering zijn, zowel wat betreft het verminderen van het vermogen als de prestaties. Er zijn echter twee mogelijke negatieve resultaten als u de 16-bits diepteindeling gebruikt.

Z-Fighting

Het verminderde dieptebereik maakt z-fighting waarschijnlijker met 16-bits dan 24-bits. Als u deze artefacten wilt voorkomen, wijzigt u de clipvlakken in near/far van de Unity-camera om rekening te houden met de lagere precisie. Voor op HoloLens gebaseerde toepassingen kan een ver klemvlak van 50 m in plaats van de unity-standaard 1000 m over het algemeen elk z-fighting elimineren.

Uitgeschakelde stencilbuffer

Wanneer Unity een weergavepatroon met 16-bits diepte maakt, wordt er geen stencilbuffer gemaakt. Als u de 24-bits diepteindeling selecteert, zoals beschreven in de Unity-documentatie, wordt er een 24-bits z-buffer en een 8-bits stencilbuffer gemaakt (als 32-bits van toepassing is op een apparaat (bijvoorbeeld de HoloLens), wat meestal het geval is).

Vermijd effecten op volledig scherm

Technieken die op het volledige scherm werken, kunnen duur zijn, omdat hun orde van grootte miljoenen bewerkingen per frame zijn. Het wordt aanbevolen om naverwerkingseffecten , zoals anti-aliasing, bloei en meer, te voorkomen.

Optimale verlichtingsinstellingen

Realtime Global Lighting in Unity kan uitstekende visuele resultaten bieden, maar omvat dure belichtingsberekeningen. We raden u aan om realtime Globale verlichting uit te schakelen voor elk Unity-scènebestand via Instellingen voorvensterweergaveverlichting>>> Schakel realtime globale verlichting uit.

Bovendien is het raadzaam om alle schaduwcasting uit te schakelen, omdat deze ook dure GPU-passen toevoegen aan een Unity-scène. Schaduwen kunnen per licht worden uitgeschakeld, maar kunnen ook holistisch worden beheerd via kwaliteitsinstellingen.

Bewerken>Projectinstellingen en selecteer vervolgens de categorie >Kwaliteit Selecteer Lage kwaliteit voor het UWP-platform. U kunt ook de eigenschap Schaduwen instellen op Schaduwen uitschakelen.

We raden u aan gebakken verlichting te gebruiken met uw modellen in Unity.

Aantal poly's verminderen

Het aantal veelhoeken wordt verminderd met een van beide

  1. Objecten verwijderen uit een scène
  2. Decimeratie van activa, waardoor het aantal veelhoeken voor een bepaald gaas wordt verminderd
  3. Een LOD-systeem (Level of Detail) implementeren in uw toepassing, waarmee objecten ver weg worden weergegeven met een lagere polygoonversie van dezelfde geometrie

Informatie over shaders in Unity

Een eenvoudige benadering om shaders in prestaties te vergelijken, is het identificeren van het gemiddelde aantal bewerkingen dat tijdens runtime wordt uitgevoerd. Dit kan eenvoudig worden gedaan in Unity.

  1. Selecteer uw shader-asset of selecteer een materiaal en selecteer vervolgens in de rechterbovenhoek van het controlevenster het tandwielpictogram gevolgd door 'Shader selecteren'

    Shader selecteren in Unity

  2. Selecteer terwijl de shader-asset is geselecteerd de knop 'Code compileren en weergeven' onder het venster Inspector

    Shader-code compileren in Unity

  3. Zoek na het compileren naar de sectie statistieken in de resultaten met het aantal verschillende bewerkingen voor zowel het hoekpunt als de pixel-shader (opmerking: pixel-shaders worden vaak ook fragment-shaders genoemd)

    Unity Standard Shader-bewerkingen

Pixel-shaders optimaliseren

Kijkend naar de gecompileerde statistische resultaten met behulp van de bovenstaande methode, zal de fragment-shader over het algemeen meer bewerkingen uitvoeren dan de hoekpunt-shader, gemiddeld. De fragment-shader, ook wel de pixel-shader genoemd, wordt uitgevoerd per pixel op de schermuitvoer, terwijl de hoekpunt-shader alleen wordt uitgevoerd per hoekpunt van alle meshes die naar het scherm worden getrokken.

Fragment-shaders hebben dus niet alleen meer instructies dan hoekpunt-shaders vanwege alle belichtingsberekeningen, maar fragment-shaders worden bijna altijd uitgevoerd op een grotere gegevensset. Als de schermuitvoer bijvoorbeeld een afbeelding van 2k bij 2k is, kan de fragment-shader 2000*2.000 = 4.000.000 keer worden uitgevoerd. Als er twee ogen worden weergegeven, verdubbelt dit getal omdat er twee schermen zijn. Als een mixed reality-toepassing meerdere passen heeft, naverwerkingseffecten op volledig scherm of meerdere meshes tot dezelfde pixel weergeeft, neemt dit aantal aanzienlijk toe.

Daarom kan het verminderen van het aantal bewerkingen in de fragment-shader over het algemeen veel betere prestaties opleveren ten opzichte van optimalisaties in de hoekpunt-shader.

Unity Standard shader alternatieven

In plaats van een fysiek gebaseerde rendering (PBR) of een andere hoogwaardige shader te gebruiken, kunt u een beter presterende en goedkopere shader gebruiken. De Mixed Reality Toolkit biedt de MRTK-standaard shader die is geoptimaliseerd voor mixed reality-projecten.

Unity biedt ook een niet-verlichte, hoekpuntverlichte, diffuse en andere vereenvoudigde arceringsopties die sneller zijn in vergelijking met de Unity Standard-shader. Zie Gebruik en prestaties van ingebouwde Shaders voor meer gedetailleerde informatie.

Shader vooraf laden

Gebruik shader vooraf laden en andere trucs om de laadtijd van de shader te optimaliseren. Met name betekent het vooraf laden van shaders dat u geen haperingen ziet vanwege runtime-shader-compilatie.

Overschrijding beperken

In Unity kan men overtekening voor de scène weergeven door het menu Tekenmodus in de linkerbovenhoek van de weergave Scène in te schakelen en Overtekenen te selecteren.

Over het algemeen kan overtekening worden verzacht door objecten van tevoren te ruimen voordat ze naar de GPU worden verzonden. Unity biedt details over het implementeren van Occlusion Culling voor hun motor.

Geheugenaanbeveling

Overmatige geheugentoewijzing & deallocatiebewerkingen kunnen nadelige gevolgen hebben voor uw holografische toepassing, wat resulteert in inconsistente prestaties, geblokkeerde frames en ander schadelijk gedrag. Het is vooral belangrijk om inzicht te hebben in geheugenoverwegingen bij het ontwikkelen in Unity, omdat geheugenbeheer wordt beheerd door de garbagecollector.

Garbagecollection

Holografische apps verliezen verwerkingstijd voor de garbage collector (GC) wanneer de GC wordt geactiveerd voor het analyseren van objecten die niet meer binnen het bereik vallen tijdens de uitvoering en hun geheugen moet worden vrijgegeven, zodat het beschikbaar kan worden gemaakt voor hergebruik. Voor constante toewijzingen en ongedaan maken van toewijzingen moet de garbagecollector over het algemeen vaker worden uitgevoerd, wat de prestaties en gebruikerservaring nadelig beïnvloedt.

Unity heeft een uitstekende pagina met gedetailleerde informatie over de werking van de garbagecollector en tips voor het schrijven van efficiëntere code met betrekking tot geheugenbeheer.

Een van de meest voorkomende procedures die leiden tot overmatige garbagecollection is niet het opslaan van verwijzingen naar onderdelen en klassen in unity-ontwikkeling. Alle verwijzingen moeten worden vastgelegd tijdens Start() of Awake() en opnieuw worden gebruikt in latere functies, zoals Update() of LateUpdate().

Andere snelle tips:

  • De C#-klasse StringBuilder gebruiken om tijdens runtime dynamisch complexe tekenreeksen te bouwen
  • Verwijder aanroepen naar Debug.Log() wanneer deze niet meer nodig zijn, omdat ze nog steeds worden uitgevoerd in alle buildversies van een app
  • Als uw holografische app over het algemeen veel geheugen vereist, kunt u overwegen Om System.GC.Collect() aan te roepen tijdens het laden, zoals bij het weergeven van een laad- of overgangsscherm

Objectgroepering

Objectgroepering is een populaire techniek voor het verlagen van de kosten van continue objecttoewijzing en deallocatie. Dit wordt gedaan door een grote pool met identieke objecten toe te wijzen en inactieve, beschikbare exemplaren uit deze pool opnieuw te gebruiken in plaats van objecten in de loop van de tijd voortdurend af te spawnen en te vernietigen. Objectgroepen zijn ideaal voor herbruikbare onderdelen met een variabele levensduur tijdens een app.

Opstartprestaties

U kunt uw app starten met een kleinere scène en vervolgens SceneManager.LoadSceneAsync gebruiken om de rest van de scène te laden. Hierdoor kan uw app zo snel mogelijk een interactieve status krijgen. Er kan een grote CPU-piek optreden terwijl de nieuwe scène wordt geactiveerd en dat weergegeven inhoud kan haperen of haperen. U kunt dit onder andere omzeilen door de eigenschap AsyncOperation.allowSceneActivation in te stellen op 'false' voor de scène die wordt geladen, te wachten tot de scène is geladen, het scherm zwart te maken en deze vervolgens weer in te stellen op 'true' om de activering van de scène te voltooien.

Houd er rekening mee dat terwijl de opstartscène wordt geladen, het holografische welkomstscherm wordt weergegeven voor de gebruiker.

Zie ook