Prestatieaanbevelingen voor Unity

Dit artikel bouwt voort op de prestatieaanbevelingen voor mixed reality, maar richt zich op Unity-specifieke verbeteringen.

We hebben onlangs een toepassing met de naam Quality Fundamentals uitgebracht, die algemene prestatie-, ontwerp- en omgevingsproblemen 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. Dit artikel bevat inhoud met enkele van de belangrijkste scèneconfiguraties voor het bouwen van performante apps voor Mixed Reality. In de volgende sectie worden enkele van deze aanbevolen instellingen toegelicht.

Hoe te profileren met Unity

Unity biedt de ingebouwde Unity Profiler , wat een geweldige bron is om waardevolle prestatie-inzichten voor uw specifieke app te verzamelen. Hoewel u de profiler in de editor kunt uitvoeren, vertegenwoordigen deze statistieken niet de echte runtime-omgeving, dus moeten resultaten voorzichtig worden gebruikt. Profileer uw toepassing op afstand terwijl deze op het apparaat wordt uitgevoerd voor de meest nauwkeurige en bruikbare inzichten.

Unity biedt geweldige documentatie voor:

  1. Hoe de Unity-profiler op afstand te verbinden met UWP-toepassingen
  2. Hoe prestatieproblemen effectief te diagnosticeren met de Unity Profiler

GPU-profilering

Unity profiler

Als de Unity Profiler is aangesloten en na het toevoegen van de GPU-profiler (zie Profiler toevoegen in de rechterbovenhoek), kan men zien hoeveel tijd er wordt besteed aan respectievelijk de CPU & GPU in het midden van de profiler. Hiermee kan de ontwikkelaar snel bepalen of hun toepassing CPU- of GPU-begrensd is.

Unity CPU versus GPU

Opmerking

Als u GPU-profilering wilt gebruiken, moet u grafische taken uitschakelen in de instellingen van de eenheidsspeler. Zie Unity's GPU Usage Profiler-module voor meer informatie.

Unity frame-foutopsporing

Unity's Frame Debugger is ook een krachtig en inzichtelijk hulpmiddel om te gebruiken. U krijgt een goed overzicht van wat de GPU elke frame doet. Dingen om op te letten zijn andere renderingdoelen en blit-commando's om hiertussen te kopiëren, aangezien deze duur zijn op HoloLens. In het ideale geval gebruikt u geen renderdoelen buiten het scherm op HoloLens. Deze worden toegevoegd bij het inschakelen van dure renderingfuncties (bijvoorbeeld MSAA, HDR of effecten op volledig scherm, zoals bloom), wat beter moet worden vermeden.

HoloLens-overlay voor framesnelheid

De pagina Systeemprestaties in Device Portal bevat een goed overzicht van de CPU- en GPU-prestaties van het apparaat. U kunt de teller Framesnelheid weergeven inschakelen in de headset en de grafiek Framesnelheid weergeven in de headset. Met deze opties worden 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-applicaties te profileren. Er zijn ook gedetailleerde instructies voor het gebruiken en installeren van PIX voor HoloLens 2. In een ontwikkelbuild worden dezelfde scopes die je ziet in Unity's Frame Debugger ook in PIX getoond en kunnen ze in meer detail worden geïnspecteerd en geprofileerd.

Opmerking

Unity biedt de mogelijkheid om eenvoudig de renderdoelresolutie van uw toepassing tijdens runtime te wijzigen via de eigenschap XRSettings.renderViewportScale . Het uiteindelijke beeld dat op het apparaat wordt weergegeven, heeft een vaste resolutie. Het platform test de uitvoer met een lagere resolutie om een afbeelding met een hogere resolutie te bouwen voor weergave op beeldschermen.

UnityEngine.XR.XRSettings.renderViewportScale = 0.7f;

Aanbevelingen voor CPU-prestaties

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

Cacheverwijzingen

We raden u aan verwijzingen naar alle relevante componenten en GameObjects bij initialisatie in de cache op te slaan, omdat herhalende functieaanroepen zoals GetComponent<T>() en Camera.main duurder zijn in verhouding tot de geheugenkosten voor het opslaan van een aanwijzer. Camera.main gebruikt gewoon FindGameObjectsWithTag() eronder, die duur in je scènegrafiek zoekt 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();
    }
}

Opmerking

Vermijd GetComponent(tekenreeks)
Wanneer je GetComponent()) gebruikt, zijn er een handvol verschillende overbelastingen. Het is belangrijk om altijd de implementaties op basis van type te gebruiken en nooit de overbelasting van zoeken op basis van tekenreeksen. Zoeken op tekenreeks in uw scène is duurder dan zoeken op type.
(Goed) Component GetComponent(typetype)
(Goed) T GetComponent<T>()
(Slecht) Component GetComponent(tekenreeks)>

Vermijd dure bewerkingen

  1. Vermijd het gebruik van LINQ

    Hoewel LINQ schoon en gemakkelijk te lezen en te schrijven is, vereist het over het algemeen meer rekenkracht en geheugen dan wanneer u het algoritme handmatig zou schrijven.

    // 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. Common Unity API's

    Bepaalde Unity-API's, hoewel nuttig, kunnen duur zijn om uit te voeren. De meeste hiervan omvatten het doorzoeken van je hele scènegrafiek voor een overeenkomende lijst met GameObjects. Deze bewerkingen kunnen over het algemeen worden vermeden door verwijzingen in de cache op te slaan of een managercomponent 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()
    

Opmerking

SendMessage() en BroadcastMessage() moeten koste wat kost worden geëlimineerd. Deze functies kunnen ongeveer 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 van het type waarde, zoals char, int, bool, enzovoort, in variabelen van het verwijzingstype. Wanneer een variabele van het waardetype in een vak wordt geplaatst, wordt deze verpakt in een System.Object, die wordt opgeslagen op de beheerde heap. Geheugen wordt toegewezen en moet uiteindelijk, wanneer het wordt weggegooid, worden verwerkt door de vuilnisman. Deze toewijzingen en deallocaties brengen prestatiekosten met zich mee en zijn in veel scenario's onnodig of kunnen gemakkelijk worden vervangen door een goedkoper alternatief.

    Om boxing te voorkomen, moet u ervoor zorgen dat de variabelen, velden en eigenschappen waarin u numerieke typen en structuren (inclusief Nullable<T>) opslaat, zijn getypt als specifieke typen zoals int, float? of MyStruct, in plaats van object te gebruiken. Als u deze objecten in een lijst plaatst, moet u een sterk getypeerde lijst gebruiken, zoals in List<int> plaats van List<object> 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

Alle herhalende Unity-callbackfuncties (d.w.z. Update) die vele malen per seconde en/of frame worden uitgevoerd, moeten zorgvuldig worden geschreven. Elke dure operatie hier heeft een enorme en consistente impact op de prestaties.

  1. Lege callbackfuncties

    Hoewel de onderstaande code misschien onschuldig lijkt om in uw toepassing te laten, vooral omdat elk Unity-script automatisch wordt geïnitialiseerd met een updatemethode, kunnen deze lege callbacks duur worden. Unity werkt heen en weer tussen een onbeheerde en beheerde codegrens, tussen UnityEngine-code en uw applicatiecode. Contextwisseling via deze brug is vrij duur, zelfs als er niets hoeft te worden uitgevoerd. Dit wordt vooral problematisch als je app honderden GameObjects heeft met onderdelen die lege herhalende Unity-callbacks hebben.

    void Update()
    {
    }
    

Opmerking

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

  1. Bewerkingen waarbij de voorkeur wordt gegeven aan één keer per frame uitvoeren

    De volgende Unity API's zijn gemeenschappelijke verrichtingen voor vele Holografische Apps. Hoewel dit niet altijd mogelijk is, kunnen de resultaten van deze functies meestal eenmaal worden berekend en worden hergebruikt in de hele toepassing voor een bepaald frame.

    1. Het is een goede gewoonte om een speciale Singleton-klasse of -service te hebben om uw blik Raycast in de scène te verwerken en dit resultaat vervolgens opnieuw te gebruiken in alle andere scènecomponenten, in plaats van herhaalde en identieke Raycast-bewerkingen uit te voeren door elk onderdeel. Sommige toepassingen vereisen raycasts van verschillende oorsprong of tegen verschillende LayerMasks.
        UnityEngine.Physics.Raycast()
        UnityEngine.Physics.RaycastAll()
    
    1. Vermijd GetComponent()-bewerkingen in herhaalde Unity-callbacks zoals Update() door verwijzingen in de cache op te slaan in Start() of Awake()
        UnityEngine.Object.GetComponent()
    
    1. Het is een goede gewoonte om alle objecten, indien mogelijk, tijdens initialisatie te instantiëren en objectpooling te gebruiken om GameObjects tijdens de runtime van uw toepassing te recyclen en opnieuw te gebruiken
        UnityEngine.Object.Instantiate()
    
  2. Vermijd interfaces en virtuele constructies

    Het aanroepen van functieaanroepen via interfaces versus directe objecten of het aanroepen van virtuele functies kan vaak veel duurder zijn dan het gebruik van directe constructies of directe functieaanroepen. Als de virtuele functie of interface niet nodig is, moet deze worden verwijderd. De prestatiehit voor deze benaderingen is echter de afweging waard als het gebruik ervan de samenwerking bij ontwikkeling, leesbaarheid van code en onderhoudbaarheid van code vereenvoudigt.

    Over het algemeen is de aanbeveling om velden en functies niet als virtueel te markeren, tenzij er een duidelijke verwachting is dat dit lid moet worden overschreven. Men moet vooral voorzichtig zijn met het gebruik van hoogfrequente codepaden die vele malen per frame of zelfs één keer 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 hun inhoud gekopieerd naar een nieuw gemaakte instantie. Deze kopie voegt CPU-kosten toe, evenals meer geheugen op de stapel. Voor kleine constructies is het effect minimaal en dus acceptabel. Echter, voor functies die herhaaldelijk elk frame aanroepen en functies die grote structs aannemen, wijzig indien mogelijk de functiedefinitie om te verwijzen naar de verwijzing. Lees hier meer

Overig

  1. Natuurkunde

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

    2. De soorten colliders in Unity hebben zeer verschillende prestatiekenmerken. In de onderstaande volgorde ziet u de meest performante colliders tot de minst performante colliders van links naar rechts. Het is belangrijk om Mesh Colliders te vermijden, die aanzienlijk duurder zijn dan de primitieve colliders.

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

  2. Animaties

    Schakel niet-actieve animaties uit door het Animator-onderdeel uit te schakelen (het uitschakelen van het gameobject heeft niet hetzelfde effect). Vermijd ontwerppatronen waarbij een animator in een lus zit en een waarde op dezelfde waarde instelt. Er is een aanzienlijke overhead voor deze techniek, zonder effect op de toepassing. Meer informatie vindt u hier.

  3. Complexe algoritmen

    Als uw toepassing complexe algoritmen gebruikt, zoals inverse kinematica, padvinding, enzovoort, zoek dan naar een eenvoudigere aanpak of pas relevante instellingen voor hun prestaties aan.

Aanbevelingen voor CPU-naar-GPU-prestaties

Over het algemeen komt de CPU-naar-GPU-prestatie neer op de trekkingsaanroepen die naar de grafische kaart worden verzonden. Om de prestaties te verbeteren, moeten draw-calls strategisch worden a) verminderd of b) geherstructureerd voor optimale resultaten. Aangezien draw-calls zelf resource-intensief zijn, zal het verminderen ervan het totale vereiste werk verminderen. Bovendien vereisen statuswijzigingen tussen draw-aanroepen dure validatie- en vertaalstappen in het grafische stuurprogramma en daarom kan het herstructureren van de draw-aanroepen van uw toepassing om statuswijzigingen te beperken (d.w.z. verschillende materialen, enz.) de prestaties verbeteren.

Unity heeft een geweldig artikel dat een overzicht geeft en duikt in batching-trekkingsoproepen voor hun platform.

Single pass instanced rendering

Single Pass Instanced Rendering in Unity maakt het mogelijk om draw-calls voor elk oog terug te brengen tot één draw-call. Vanwege cache-coherentie tussen twee draw-aanroepen is er ook enige prestatieverbetering op de GPU.

Deze functie inschakelen in uw Unity-project

  1. Open OpenXR-instellingen (ga naarProjectinstellingen>bewerken>,XR-plug-inbeheer>,OpenXR).
  2. Selecteer Single Pass Instanced in de vervolgkeuzelijst Rendermodus .

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

Opmerking

Een veelvoorkomend probleem met Single Pass Instanced Rendering doet zich voor als ontwikkelaars al bestaande aangepaste shaders hebben die niet zijn geschreven voor Instancing. Na het inschakelen van deze functie kunnen ontwikkelaars merken dat sommige GameObjects slechts in één oog worden weergegeven. Dit komt omdat de bijbehorende aangepaste shaders niet de juiste eigenschappen hebben voor instancing.

Statische batching

Unity is in staat om veel statische objecten te batchen om draw-aanroepen naar de GPU te verminderen. Static Batching 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 controle in). GameObjects die zijn gemarkeerd als statisch , kunnen niet worden verplaatst tijdens de runtime van uw toepassing. Statische batching kan dus moeilijk worden toegepast op HoloLens, waar vrijwel elk object moet worden geplaatst, verplaatst, geschaald, enzovoort. Voor immersive headsets kan statische batching het aantal draw-calls drastisch verminderen en zo de prestaties verbeteren.

Lees Static Batching under Draw Call Batching in Unity voor meer informatie.

Dynamische batching

Aangezien het problematisch is om objecten als statisch te markeren voor HoloLens-ontwikkeling, kan dynamische batching een uitstekend hulpmiddel zijn om deze ontbrekende functie te compenseren. Het kan ook handig zijn op immersive headsets. Het kan echter lastig zijn om dynamische batches in Unity in te schakelen omdat GameObjects a) hetzelfde materiaal moet delen en b) aan een lange lijst met andere criteria moet voldoen.

Lees Dynamische batching onder Draw Call Batching in Unity voor de volledige lijst. Meestal worden GameObjects ongeldig om dynamisch in batches te worden verzonden, omdat de bijbehorende mesh-gegevens niet meer dan 300 hoekpunten mogen bevatten.

Andere technieken

Batching kan alleen plaatsvinden als meerdere GameObjects hetzelfde materiaal kunnen delen. Meestal wordt dit geblokkeerd door de noodzaak voor GameObjects om een unieke textuur te hebben voor hun respectievelijke materiaal. Het is gebruikelijk om texturen te combineren tot één grote textuur, een methode die bekend staat als Texture Atlasing.

Bovendien verdient het de voorkeur om meshes te combineren tot één GameObject waar mogelijk en redelijk. Elke renderer in Unity heeft zijn bijbehorende draw call versus het indienen van een gecombineerde mesh onder één Renderer.

Opmerking

Het wijzigen van de eigenschappen van Renderer.material tijdens runtime maakt een kopie van het materiaal en verbreekt dus mogelijk de batching. Gebruik Renderer.sharedMaterial om gedeelde materiaaleigenschappen tussen GameObjects te wijzigen.

Aanbevelingen voor GPU-prestaties

Bandbreedte en opvullingspercentages

Bij het renderen van een frame op de GPU is een toepassing ofwel gebonden aan geheugenbandbreedte of vulsnelheid.

  • Geheugenbandbreedte is de snelheid van lezen en schrijven die de GPU uit het geheugen kan doen
  • Fill rate verwijst naar de pixels die per seconde door de GPU kunnen worden getrokken.

Dieptebuffer delen optimaliseren

Het is raadzaam om dieptebuffer delen in te schakelen om de stabiliteit van hologrammen te optimaliseren. Als u met deze instelling herprojectie op basis van diepte in een laat stadium inschakelt, raden wij u aan de 16-bits diepte-indeling te selecteren in plaats van de 24-bits diepte-indeling. De 16-bits dieptebuffers zullen de bandbreedte (en dus het vermogen) die gepaard gaat met dieptebufferverkeer drastisch verminderen. Dit kan een grote verbetering zijn, zowel in vermogensreductie als in prestaties. Er zijn echter twee mogelijke negatieve gevolgen van het gebruik van 16-bits diepte-indeling.

Z-vechten

Door de verminderde getrouwheid van het dieptebereik is de kans groter dat z-gevechten optreden met 16-bits dan met 24-bits. Om deze artefacten te voorkomen, wijzigt u de dichtbij/veraf clipvlakken van de Unity-camera om rekening te houden met de lagere precisie. Voor HoloLens-gebaseerde toepassingen kan een ver clipvlak van 50 m in plaats van de Unity standaard 1.000 m over het algemeen z-gevechten elimineren.

Uitgeschakelde stencilbuffer

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

Effecten op volledig scherm vermijden

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

Optimale belichtingsinstellingen

Real-time Global Illumination in Unity kan uitstekende visuele resultaten opleveren, maar omvat dure verlichtingsberekeningen. We raden aan om real-time globale verlichting uit te schakelen voor elk Unity-scènebestand viaVerlichtingsinstellingen> voorvensterweergave>> Schakel Real-time globale verlichting uit.

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

Bewerken>Projectinstellingen en selecteer vervolgens de kwaliteitscategorie > en selecteer Lage kwaliteit voor het UWP-platform. Men kan ook gewoon de eigenschap Schaduwen instellen op Schaduwen uitschakelen.

We raden je aan om gebakken verlichting te gebruiken met je modellen in Unity.

Het aantal polygraden verminderen

Het aantal polygonen wordt verminderd met

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

Understanding shaders in Unity

Een eenvoudige benadering om shaders in prestaties te vergelijken, is door het gemiddelde aantal bewerkingen te identificeren dat elk tijdens runtime uitvoert. Dit kan eenvoudig in Unity.

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

    Arcering selecteren in Unity

  2. Selecteer de shader-asset en selecteer de knop 'Code compileren en weergeven' onder het controlevenster.

    Shadercode compileren in Unity

  3. Zoek na het compileren naar de statistische sectie in de resultaten met het aantal verschillende bewerkingen voor zowel de vertex als de pixel shader (Opmerking: pixel shaders worden vaak ook wel fragment shaders genoemd).

    Unity Standard Shader-bewerkingen

Optimaliseer pixel shaders

Als we kijken naar de gecompileerde statistische resultaten met behulp van de bovenstaande methode, zal de fragment shader over het algemeen gemiddeld meer bewerkingen uitvoeren dan de vertex shader. De fragment shader, ook bekend als de pixel shader, wordt uitgevoerd per pixel op de schermuitvoer, terwijl de vertex shader alleen wordt uitgevoerd per vertex van alle meshes die naar het scherm worden getrokken.

Niet alleen hebben fragment shaders dus meer instructies dan vertex shaders vanwege alle lichtberekeningen, fragment shaders worden bijna altijd uitgevoerd op een grotere dataset. Als de schermuitvoer bijvoorbeeld een afbeelding van 2k bij 2k is, kan de fragment-shader 2.000*2.000 = 4.000.000 keer worden uitgevoerd. Als er twee ogen worden weergegeven, verdubbelt dit getal omdat er twee schermen zijn. Als een toepassing voor mixed reality meerdere passages heeft, nabewerkingseffecten op volledig scherm heeft of meerdere meshes naar dezelfde pixel rendert, neemt dit getal drastisch toe.

Daarom kan het verminderen van het aantal bewerkingen in de fragment-shader over het algemeen veel grotere prestatieverbeteringen opleveren dan optimalisaties in de vertex shader.

Unity Standard shader-alternatieven

In plaats van een fysiek gebaseerde weergave (PBR) of een andere shader van hoge kwaliteit te gebruiken, kunt u kijken naar het gebruik van een meer performante en goedkopere shader. De Mixed Reality Toolkit bevat de MRTK-standaardshader die is geoptimaliseerd voor mixed reality-projecten.

Unity biedt ook een onverlichte, vertex verlit, diffuse en andere vereenvoudigde shader-opties die sneller zijn in vergelijking met de Unity Standard-shader. Zie Gebruik en prestaties van ingebouwde shaders voor meer informatie.

Shader vooraf laden

Gebruik Shader, vooraf laden en andere trucs om de laadtijd van shaders te optimaliseren. Met name het vooraf laden van shader betekent dat u geen haperingen zult zien als gevolg van runtime shader-compilatie.

Beperk rood staan

In Unity kan men overschrijven weergeven voor hun scène, door het menu tekenmodus in de linkerbovenhoek van de Scèneweergave in te schakelen en Overtekenen te selecteren.

Over het algemeen kan overbelasting worden beperkt door objecten van tevoren te verwijderen voordat ze naar de GPU worden gestuurd. Unity geeft details over het implementeren van Occlusion Culling voor hun motor.

Aanbevelingen voor geheugen

Overmatige geheugentoewijzing & toewijzingsbewerkingen kunnen nadelige gevolgen hebben voor de holografische toepassing, wat kan leiden tot inconsistente prestaties, stilstaande frames en ander nadelig gedrag. Het is vooral belangrijk om geheugenoverwegingen te begrijpen bij het ontwikkelen in Unity, omdat geheugenbeheer wordt beheerd door de vuilnisman.

Vuilnisophaaldienst

Holografische apps verliezen verwerkingsrekentijd aan de garbage collector (GC) wanneer de GC wordt geactiveerd om objecten te analyseren die niet meer binnen het bereik vallen tijdens de uitvoering en hun geheugen moet worden vrijgegeven zodat het beschikbaar kan worden gemaakt voor hergebruik. Constante toewijzingen en de-toewijzingen vereisen over het algemeen dat de vuilnisophaler vaker draait, wat de prestaties en gebruikerservaring schaadt.

Een van de meest voorkomende praktijken die leidt tot overmatige afvalinzameling, is het niet cachen van verwijzingen naar componenten en klassen in Unity-ontwikkeling. Alle verwijzingen moeten worden vastgelegd tijdens Start() of Awake() en worden hergebruikt in latere functies zoals Update() of LateUpdate().

Andere snelle tips:

  • Gebruik de klasse StringBuilder C# om tijdens runtime dynamisch complexe tekenreeksen te bouwen.
  • Verwijder aanroepen naar Debug.Log() wanneer ze 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 nodig heeft, kunt u System.GC.Collect() aanroepen tijdens laadfasen, bijvoorbeeld bij het presenteren van een laad- of overgangsscherm.

Pooling van objecten

Object pooling is een populaire techniek om de kosten van continue objecttoewijzing en deallocaties te verlagen. Dit wordt gedaan door een grote pool van identieke objecten toe te wijzen en inactieve, beschikbare exemplaren uit deze pool opnieuw te gebruiken in plaats van constant objecten te spawnen en te vernietigen in de loop van de tijd. Objectgroepen zijn zeer geschikt voor herbruikbare onderdelen met een variabele levensduur tijdens een app.

Opstartprestaties

Overweeg om uw app te starten met een kleinere scène en vervolgens SceneManager.LoadSceneAsync te gebruiken om de rest van de scène te laden. Hierdoor kan je app zo snel mogelijk een interactieve status krijgen. Er kan een grote CPU-piek optreden terwijl de nieuwe scène wordt geactiveerd en dat gerenderde inhoud kan haperen of haperen. Een manier om dit probleem te omzeilen, is door de eigenschap AsyncOperation.allowSceneActivation in te stellen op 'false' op de scène die wordt geladen, te wachten totdat de scène is geladen, het scherm te wissen tot zwart en vervolgens weer 'true' te zetten om de scèneactivering te voltooien.

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