Prestandarekommendationer för Unity
Den här artikeln bygger på prestandarekommendationerna för mixad verklighet, men fokuserar på Unity-specifika förbättringar.
Vi släppte nyligen ett program som heter Kvalitetsgrunder som omfattar vanliga prestanda-, design- och miljöproblem och lösningar för HoloLens 2 appar. Den här appen är en bra visuell demo för det innehåll som följer.
Använd rekommenderade Unity-projektinställningar
Det viktigaste första steget när du optimerar prestanda för appar med mixad verklighet i Unity är att se till att du använder de rekommenderade miljöinställningarna för Unity. Artikeln innehåller innehåll med några av de viktigaste scenkonfigurationerna för att skapa högpresterande Mixed Reality appar. Några av de här rekommenderade inställningarna är också markerade nedan.
Profilera med Unity
Unity tillhandahåller Unity Profiler inbyggt, vilket är en bra resurs för att samla in värdefulla prestandainsikter för din app. Även om du kan köra profileraren i redigeringsprogrammet representerar dessa mått inte den sanna körningsmiljön, så resultatet bör användas försiktigt. Vi rekommenderar att du fjärrprofilerar ditt program när du kör på enheten för att få de mest exakta och användbara insikterna.
Unity tillhandahåller bra dokumentation för:
- Fjärransluta Unity Profiler till UWP-program
- Så här diagnostiserar du prestandaproblem effektivt med Unity Profiler
GPU-profilering
Unity Profiler
När Unity Profiler är ansluten och efter att GPU-profileraren har lagts till (se Lägg till profilerare i det övre högra hörnet) kan man se hur mycket tid som spenderas på processorn & GPU i mitten av profileraren. På så sätt kan utvecklaren få en snabb uppskattning om deras program är cpu- eller GPU-begränsat.
Anteckning
Om du vill använda GPU-profilering måste du inaktivera grafikjobb i Unity Player-inställningarna. Mer information finns i Unitys modul GPU Usage Profiler .
Felsökningsprogram för Unity-bildruta
Unitys Frame Debugger är också ett kraftfullt och insiktsfullt verktyg att använda. Det ger dig en bra översikt över vad GPU:n gör varje bildruta. Saker att hålla utkik efter är ytterligare återgivningsmål och blit-kommandon att kopiera mellan dem eftersom dessa är mycket dyra på HoloLens. Helst ska inga mål för återgivning utanför skärmen användas på HoloLens. Dessa läggs vanligtvis till när du aktiverar dyra återgivningsfunktioner (till exempel MSAA, HDR eller helskärmseffekter som bloom) som bör undvikas.
Överlägg för HoloLens-bildfrekvens
På sidan Systemprestanda för enhetsportalen finns en bra sammanfattning av enhetens PROCESSOR- och GPU-prestanda. Du kan aktivera Display frame rate counter in headset (Visa bildfrekvensräknare i headsetet ) och Display frame rate graph in headset (Visa bildfrekvensdiagram i headsetet). De här alternativen aktiverar en FPS-räknare respektive graf som ger dig omedelbar feedback i alla program som körs på din enhet.
PIX
PIX kan även användas för att profilera Unity-program. Det finns också detaljerade instruktioner om hur du använder och installerar PIX för HoloLens 2. I en utvecklingsversion visas samma omfång som du ser i Unitys Frame Debugger även i PIX och kan inspekteras och profileras mer detaljerat.
Anteckning
Unity ger dig möjlighet att enkelt ändra programmets återgivningsmålmatchning vid körning via egenskapen XRSettings.renderViewportScale . Den slutliga avbildningen som visas på enheten har en fast upplösning. Plattformen provar utdata med lägre upplösning för att skapa en bild med högre upplösning för återgivning på skärmar.
UnityEngine.XR.XRSettings.renderViewportScale = 0.7f;
Rekommendationer för CPU-prestanda
Innehållet nedan beskriver mer djupgående prestandametoder, särskilt för Unity-& C#-utveckling.
Cachereferenser
Vi rekommenderar att du cachelagrar referenser till alla relevanta komponenter och GameObjects vid initieringen eftersom upprepade funktionsanrop som GetComponent<T>() och Camera.main är dyrare i förhållande till minneskostnaden för att lagra en pekare. . Camera.main använder bara FindGameObjectsWithTag() under, som dyrt söker i ditt scendiagram efter ett kameraobjekt med taggen "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();
}
}
Anteckning
Undvik GetComponent(sträng)
När du använder GetComponent()finns det några olika överlagringar. Det är viktigt att alltid använda de typbaserade implementeringarna och aldrig den strängbaserade sökningens överbelastning. Det är betydligt dyrare att söka efter sträng i scenen än att söka efter typ.
(Bra) Komponenten GetComponent(typ)
(Bra) T GetComponent<T>()
(Dåligt) Komponenten GetComponent(sträng)>
Undvik kostsamma åtgärder
Undvik användning av LINQ
Även om LINQ kan vara rent och enkelt att läsa och skriva kräver det vanligtvis mer beräkning och minne än om du skrev algoritmen manuellt.
// 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;
Vanliga Unity-API:er
Vissa Unity-API:er kan, även om de är användbara, vara dyra att köra. De flesta av dessa handlar om att söka i hela scendiagrammet efter en matchande lista över GameObjects. Dessa åtgärder kan vanligtvis undvikas genom att cachelagra referenser eller implementera en hanteringskomponent för GameObjects för att spåra referenserna vid körning.
GameObject.SendMessage() GameObject.BroadcastMessage() UnityEngine.Object.Find() UnityEngine.Object.FindWithTag() UnityEngine.Object.FindObjectOfType() UnityEngine.Object.FindObjectsOfType() UnityEngine.Object.FindGameObjectsWithTag() UnityEngine.Object.FindGameObjectsWithTag()
Anteckning
SendMessage() och BroadcastMessage() bör elimineras till varje pris. Dessa funktioner kan vara i ordning 1 000 gånger långsammare än direkta funktionsanrop.
Akta dig för boxning
Boxning är ett grundläggande begrepp inom språket och körningen i C#. Det är processen att omsluta värdetypsvariabler som
char
,int
,bool
osv. i referenstypade variabler. När en värdetypsvariabel är "boxad" omsluts den i enSystem.Object
, som lagras på den hanterade heapen. Minne allokeras och så småningom när borttaget måste bearbetas av skräpinsamlaren. Dessa allokeringar och frigöringar medför en prestandakostnad och är i många fall onödiga eller kan enkelt ersättas av ett billigare alternativ.För att undvika boxning måste du se till att de variabler, fält och egenskaper där du lagrar numeriska typer och structs (inklusive
Nullable<T>
) är starkt typifierade som specifika typer somint
,float?
ellerMyStruct
, i stället för att använda objekt. Om du placerar dessa objekt i en lista bör du använda en starkt typifierad lista, till exempelList<int>
i ställetList<object>
för ellerArrayList
.Exempel på boxning i C#
// boolean value type is boxed into object boxedMyVar on the heap bool myVar = true; object boxedMyVar = myVar;
Sökvägar för upprepande kod
Alla upprepade återanropsfunktioner i Unity (t.ex. uppdatering) som körs många gånger per sekund och/eller bildruta bör skrivas noggrant. Alla dyra åtgärder här kommer att ha en enorm och konsekvent inverkan på prestandan.
Tomma återanropsfunktioner
Även om koden nedan kan verka oskyldig att lämna i ditt program, särskilt eftersom varje Unity-skript initieras automatiskt med en Uppdateringsmetod, kan dessa tomma återanrop bli dyra. Unity fungerar fram och tillbaka mellan en ohanterad och hanterad kodgräns mellan UnityEngine-koden och din programkod. Kontextväxling över den här bryggan är ganska dyrt, även om det inte finns något att köra. Detta blir särskilt problematiskt om din app har 100-talet GameObjects med komponenter som har tomma upprepade Unity-återanrop.
void Update() { }
Anteckning
Update() är den vanligaste manifestationen av det här prestandaproblemet, men andra upprepade Unity-återanrop, till exempel följande kan vara lika dåliga, om inte värre: FixedUpdate(), LateUpdate(), OnPostRender", OnPreRender(), OnRenderImage(), osv.
Åtgärder för att prioritera körning en gång per bildruta
Följande Unity-API:er är vanliga åtgärder för många Holographic Apps. Även om det inte alltid är möjligt kan resultaten från dessa funktioner ofta beräknas en gång och resultaten återanvändas i hela programmet för en viss ram.
a) Det är bra att ha en dedikerad Singleton-klass eller -tjänst för att hantera din blick Raycast in i scenen och sedan återanvända detta resultat i alla andra scenkomponenter, istället för att göra upprepade och identiska Raycast-åtgärder av varje komponent. Vissa program kan kräva raycasts från olika ursprung eller mot olika LayerMasks.
UnityEngine.Physics.Raycast() UnityEngine.Physics.RaycastAll()
b) Undvik GetComponent()-åtgärder i upprepade Unity-återanrop som Update() genom att cachelagra referenser i Start() eller Awake()
UnityEngine.Object.GetComponent()
c) Det är bra att instansiera alla objekt, om möjligt, vid initiering och använda objektpooler för att återvinna och återanvända GameObjects under hela körningen av ditt program
UnityEngine.Object.Instantiate()
Undvik gränssnitt och virtuella konstruktioner
Att anropa funktionsanrop via gränssnitt jämfört med direkta objekt eller anropa virtuella funktioner kan ofta vara mycket dyrare än att använda direkta konstruktioner eller direkta funktionsanrop. Om den virtuella funktionen eller gränssnittet är onödigt bör det tas bort. Prestandaresultatet för dessa metoder är dock värt kompromissen om användningen av dem förenklar utvecklingssamarbete, kodläsning och kodunderhåll.
I allmänhet är rekommendationen att inte markera fält och funktioner som virtuella om det inte finns en tydlig förväntan på att den här medlemmen måste skrivas över. Man bör vara särskilt försiktig med kodsökvägar med hög frekvens som anropas många gånger per bildruta eller till och med en gång per bildruta, till exempel en
UpdateUI()
metod.Undvik att skicka structs efter värde
Till skillnad från klasser är structs värdetyper och när de skickas direkt till en funktion kopieras deras innehåll till en nyligen skapad instans. Den här kopian lägger till cpu-kostnad samt ytterligare minne på stacken. För små structs är effekten minimal och därmed acceptabel. Men för funktioner som anropas upprepade gånger varje bildruta samt funktioner som tar stora strukturer, ändrar du om möjligt funktionsdefinitionen så att den skickas med referens. Läs mer här
Övriga farliga ämnen
Fysik
a) I allmänhet är det enklaste sättet att förbättra fysiken att begränsa den tid som ägnas åt fysik eller antalet iterationer per sekund. Detta minskar simuleringsprecisionen. Se TimeManager i Unity
b) Typerna av kolliderare i Unity har mycket olika prestandaegenskaper. I ordningen nedan visas de mest högpresterande kolliderarna till minst högpresterande kolliderare från vänster till höger. Det är viktigt att undvika Mesh Colliders, som är betydligt dyrare än de primitiva kolliderarna.
Sphere < Capsule < Box <<< Mesh (konvex) < Nät (icke-konvex)
Mer information finns i Metodtips för Unity-fysik
Animeringar
Inaktivera inaktiva animeringar genom att inaktivera Animator-komponenten (om du inaktiverar spelobjektet får du inte samma effekt). Undvik designmönster där en animatör finns i en loop och anger ett värde till samma sak. Det finns betydande omkostnader för den här tekniken, utan att programmet påverkas. Mer information finns här.
Komplexa algoritmer
Om ditt program använder komplexa algoritmer som inverterade kinematik, sökvägssökning osv. kan du leta efter en enklare metod eller justera relevanta inställningar för deras prestanda
Prestandarekommendationer för cpu-till-GPU
I allmänhet beror CPU-till-GPU-prestanda på de anrop som skickas till grafikkortet. För att förbättra prestandan måste anrop göras strategiskt a) minskas eller b) omstruktureras för optimala resultat. Eftersom själva anropen är resursintensiva minskar det totala arbete som krävs om du minskar dem. Dessutom kräver tillståndsändringar mellan anrop kostsamma validerings- och översättningssteg i grafikdrivrutinen och därmed kan omstrukturering av programmets anrop för att begränsa tillståndsändringar (dvs. olika material osv.) öka prestandan.
Unity har en bra artikel som ger en översikt och går in i batchdragningsanrop för deras plattform.
Rendering med enkel pass-instans
Med Single Pass Instanced Rendering i Unity kan anrop för varje öga reduceras till ett instansanrop. På grund av cachesammansekvensen mellan två anrop finns det även vissa prestandaförbättringar för GPU:n.
Så här aktiverar du den här funktionen i ditt Unity-projekt
- Öppna OpenXR-inställningar (gå till Redigera>projektinställningar>XR Plugin Management>OpenXR).
- Välj Single Pass Instanced i den nedrullningsbara menyn Rendera läge .
Läs följande artiklar från Unity för mer information om den här återgivningsmetoden.
Anteckning
Ett vanligt problem med Single Pass Instanced Rendering uppstår om utvecklare redan har befintliga anpassade skuggor som inte har skrivits för instancing. När du har aktiverat den här funktionen kan utvecklare märka att vissa GameObjects bara renderas i ett öga. Det beror på att de associerade anpassade skuggningarna inte har lämpliga egenskaper för instancing.
Se Stereorendering med enkel pass för HoloLens från Unity för information om hur du åtgärdar det här problemet
Statisk batchbearbetning
Unity kan batcha många statiska objekt för att minska anrop till GPU:n. Statisk batchbearbetning fungerar för de flesta renderarobjekt i Unity som 1) delar samma material och 2) markeras alla som statiska (markera ett objekt i Unity och markera kryssrutan längst upp till höger i inspektören). GameObjects som markerats som statiska kan inte flyttas under programmets körning. Statisk batchbearbetning kan därför vara svår att utnyttja på HoloLens där praktiskt taget alla objekt måste placeras, flyttas, skalas osv. För integrerande headset kan statisk batchbearbetning avsevärt minska antalet anrop och därmed förbättra prestandan.
Mer information finns i Statisk batchbearbetning under Batchbearbetning av anropsdragning i Unity .
Dynamisk batchbearbetning
Eftersom det är problematiskt att markera objekt som statiska för HoloLens-utveckling kan dynamisk batchbearbetning vara ett bra verktyg för att kompensera för den saknade funktionen. Det kan också vara användbart på integrerande headset också. Dynamisk batchbearbetning i Unity kan dock vara svårt att aktivera eftersom GameObjects måste a) dela samma material och b) uppfylla en lång lista med andra kriterier.
Läs Dynamisk batchbearbetning under Batchbearbetning av anrop i Unity för den fullständiga listan. Vanligtvis blir GameObjects ogiltiga för batchbearbetning dynamiskt, eftersom associerade nätdata inte får vara fler än 300 hörn.
Andra tekniker
Batchbearbetning kan bara ske om flera GameObjects kan dela samma material. Detta blockeras vanligtvis av behovet av att GameObjects har en unik struktur för respektive material. Det är vanligt att kombinera texturer till en stor textur, en metod som kallas Texture Atlasing.
Dessutom är det bättre att kombinera nät till ett GameObject där det är möjligt och rimligt. Varje renderare i Unity får sina associerade anrop jämfört med att skicka ett kombinerat nät under en renderare.
Anteckning
Om du ändrar egenskaperna för Renderer.material vid körning skapas en kopia av materialet och därmed kan batchbearbetningen brytas. Använd Renderer.sharedMaterial för att ändra egenskaper för delat material i GameObjects.
GPU-prestandarekommendationer
Läs mer om hur du optimerar grafikrendering i Unity
Bandbredds- och fyllningshastigheter
När du återger en ram på GPU:n är ett program antingen bundet av minnesbandbredd eller fyllningshastighet.
- Minnesbandbredd är frekvensen för läsningar och skrivningar som GPU:n kan göra från minnet
- I Unity ändrar du Texturkvalitet i Redigera>kvalitetsinställningar förprojektinställningar>.
- Fyllningsfrekvensen refererar till de bildpunkter som kan ritas per sekund av GPU:n.
- I Unity använder du egenskapen XRSettings.renderViewportScale .
Optimera delning av djupbuffert
Vi rekommenderar att du aktiverar delning av djupbuffert för att optimera för hologramstabilitet. När du aktiverar djupbaserad omprojektion i sent skede med den här inställningen rekommenderar vi att du väljer 16-bitars djupformat i stället för 24-bitars djupformat. 16-bitars djupbuffertar minskar drastiskt den bandbredd (och därmed ström) som är associerad med djupbufferttrafik. Detta kan vara en stor förbättring både vad gäller energiminskning och prestanda. Det finns dock två möjliga negativa resultat med hjälp av 16-bitars djupformat.
Z-Fighting
Den reducerade djupområdesåtergivningen gör z-fighting mer sannolikt att inträffa med 16 bitar än 24-bitars. För att undvika dessa artefakter ändrar du unity-kamerans när-/fjärran-klippplan för att ta hänsyn till den lägre precisionen. För HoloLens-baserade program kan ett långt klippplan på 50 m i stället för Unity-standardvärdet 1000 m i allmänhet eliminera z-fighting.
Inaktiverad stencilbuffert
När Unity skapar en renderingsstruktur med 16-bitars djup skapas ingen stencilbuffert. Om du väljer 24-bitars djupformat, enligt beskrivningen i Unity-dokumentationen, skapas en 24-bitars z-buffert och en 8-bitars stencilbuffert (om 32-bitars är tillämpligt på en enhet (till exempel HoloLens), vilket vanligtvis är fallet).
Undvik helskärmseffekter
Tekniker som körs på helskärmsläge kan vara dyra eftersom deras storleksordning är miljontals åtgärder varje bildruta. Vi rekommenderar att du undviker efterbearbetningseffekter som aliasutjämning, blomning med mera.
Optimala belysningsinställningar
Global belysning i realtid i Unity kan ge enastående visuella resultat men omfattar dyra ljusberäkningar. Vi rekommenderar att du inaktiverar global belysning i realtid för varje Unity-scenfil via Inställningar> förfönsterrenderingsbelysning>> Avmarkera Global belysning i realtid.
Dessutom rekommenderar vi att du inaktiverar all skugggjutning eftersom dessa också lägger till dyra GPU-pass till en Unity-scen. Skuggor kan inaktiveras per ljus men kan också kontrolleras holistiskt via kvalitetsinställningar.
Redigera>Projektinställningar och välj sedan kategorin >Kvalitet Välj Låg kvalitet för UWP-plattformen. Man kan också ange egenskapen Shadows till Inaktivera skuggor.
Vi rekommenderar att du använder bakad belysning med dina modeller i Unity.
Minska antalet poly
Antalet polygoner minskas med antingen
- Ta bort objekt från en scen
- Decimering av tillgångar, vilket minskar antalet polygoner för ett givet nät
- Implementera ett LOD-system (Level of Detail) i ditt program, som återger långt borta-objekt med lägre polygonversion av samma geometri
Förstå skuggningar i Unity
En enkel uppskattning för att jämföra skuggningar i prestanda är att identifiera det genomsnittliga antalet åtgärder som varje kör vid körning. Detta kan göras enkelt i Unity.
Välj din skuggningstillgång eller välj ett material. I det övre högra hörnet i kontrollfönstret väljer du kugghjulsikonen följt av "Välj skuggning"
När skuggningstillgången är markerad väljer du knappen Kompilera och visa kod under kontrollfönstret
När du har kompilerats letar du efter statistikavsnittet i resultaten med antalet olika åtgärder för både hörn och pixelskuggning (Obs! pixelskuggare kallas ofta även fragmentskuggare)
Optimera pixelskuggare
Om du tittar på de kompilerade statistikresultaten med metoden ovan kör fragmentskuggaren vanligtvis fler åtgärder än hörnskuggningen i genomsnitt. Fragmentskuggaren, även kallad pixelskuggare, körs per bildpunkt på skärmens utdata medan hörnskuggningen bara körs per hörn av alla nät som ritas till skärmen.
Därför har inte bara fragmentskuggare fler instruktioner än hörnskuggor på grund av alla ljusberäkningar, fragmentskuggare körs nästan alltid på en större datauppsättning. Om skärmutdata till exempel är en bild på 2 000 gånger 2 000 kan fragmentskuggaren köras 2 000*2 000 = 4 000 000 gånger. Om du återger två ögon fördubblas det här antalet eftersom det finns två skärmar. Om ett mixed reality-program har flera passeringar, fullskärmseffekter efter bearbetning eller återgivning av flera nät till samma pixel, ökar det här antalet dramatiskt.
Därför kan en minskning av antalet åtgärder i fragmentskuggningen i allmänhet ge mycket större prestandavinster jämfört med optimeringar i hörnskuggningen.
Alternativ för Unity Standard-skuggning
I stället för att använda en fysiskt baserad rendering (PBR) eller en annan skuggning av hög kvalitet kan du titta på att använda en mer högpresterande och billigare skuggning. Mixed Reality Toolkit tillhandahåller standardskuggningen MRTK som har optimerats för projekt med mixad verklighet.
Unity ger också ett oupplyst hörn upplyst, diffust och andra förenklade skuggningsalternativ som är snabbare jämfört med Unity Standard-skuggningen. Mer detaljerad information finns i Användning och prestanda för inbyggda skuggor .
Förinläsning av skuggning
Använd Shader-förinläsning och andra knep för att optimera skuggningstiden. I synnerhet innebär skuggningsförläsning att du inte ser några problem på grund av körningsskuggningskompilering.
Begränsa övertrassering
I Unity kan man visa övertrassering för sin scen genom att växla ritlägesmenyn i det övre vänstra hörnet i scenvyn och välja Övertrassering.
I allmänhet kan övertrassering minimeras genom utgallring av objekt i förväg innan de skickas till GPU:n. Unity innehåller information om hur du implementerar Occlusion Culling för motorn.
Minnesrekommendationer
Överdriven minnesallokering & frigöringsåtgärder kan ha negativa effekter på ditt holografiska program, vilket resulterar i inkonsekventa prestanda, låsta ramar och annat skadligt beteende. Det är särskilt viktigt att förstå minnesöverväganden när du utvecklar i Unity eftersom minneshantering styrs av skräpinsamlaren.
Skräpinsamling
Holografiska appar förlorar bearbetningstiden för beräkning till skräpinsamlaren (GC) när GC aktiveras för att analysera objekt som inte längre finns i omfånget under körningen och deras minne måste frigöras, så att det kan göras tillgängligt för återanvändning. Konstanta allokeringar och avallokeringar kräver vanligtvis att skräpinsamlaren körs oftare, vilket skadar prestanda och användarupplevelsen.
Unity har gett en utmärkt sida som förklarar i detalj hur skräpinsamlaren fungerar och tips för att skriva effektivare kod när det gäller minneshantering.
En av de vanligaste metoderna som leder till överdriven skräpinsamling är inte cachelagringsreferenser till komponenter och klasser i Unity-utveckling. Referenser ska samlas in under Start() eller Awake() och återanvändas i senare funktioner som Update() eller LateUpdate().
Andra snabbtips:
- Använd klassen StringBuilder C# för att dynamiskt skapa komplexa strängar vid körning
- Ta bort anrop till Debug.Log() när de inte längre behövs, eftersom de fortfarande körs i alla versionsversioner av en app
- Om din holografiska app vanligtvis kräver mycket minne bör du överväga att anropa System.GC.Collect() under inläsningsfaser, till exempel när du presenterar en inläsnings- eller övergångsskärm
Objektpooler
Objektpooler är en populär metod för att minska kostnaden för kontinuerlig objektallokering och frigöring. Detta görs genom att allokera en stor pool med identiska objekt och återanvända inaktiva, tillgängliga instanser från den här poolen i stället för att ständigt skapa och förstöra objekt över tid. Objektpooler är bra för återanvändbara komponenter som har variabel livslängd under en app.
Startprestanda
Överväg att starta appen med en mindre scen och sedan använda SceneManager.LoadSceneAsync för att läsa in resten av scenen. På så sätt kan din app komma till ett interaktivt tillstånd så snabbt som möjligt. Det kan finnas en stor CPU-topp medan den nya scenen aktiveras och att allt renderat innehåll kan stamma eller koppla. Ett sätt att kringgå detta är att ställa in egenskapen AsyncOperation.allowSceneActivation på "false" på scenen som läses in, vänta tills scenen läses in, rensa skärmen till svart och sedan ställa in den på "true" för att slutföra scenaktiveringen.
Kom ihåg att medan startscenen läses in visas den holografiska välkomstskärmen för användaren.