Why is mobile game optimization important?

Optimal Ydeevne: Guide til Mobilspilsoptimering i Unity

15/10/2022

Rating: 4.18 (3598 votes)

I dagens mobile landskab er forventningerne til spillets ydeevne højere end nogensinde. Brugere forventer flydende gameplay, hurtige indlæsningstider og minimalt batteriforbrug, uanset hvilken enhed de bruger. At levere en sådan oplevelse kræver omhyggelig optimering, især når man udvikler med en kraftfuld motor som Unity. Denne artikel vil udforske de mange facetter af mobilspilsoptimering, fra den grundlæggende kode til den avancerede håndtering af spillets aktiver, og give dig de værktøjer, du skal bruge for at sikre, at dit spil kører optimalt på alle mobile platforme.

Why is mobile game optimization important?
Mobile hardware continues to evolve, and a mobile game’s optimization – along with art, game design, audio, and monetization strategy – plays a key role in shaping the player experience. This guide provides knowledge and advice from Unity’s expert team of software engineers.

Uanset om du er en erfaren udvikler eller lige er begyndt, er forståelsen af disse optimeringsteknikker afgørende for succes. Et dårligt optimeret spil kan føre til frustration, dårlige anmeldelser og i sidste ende et lavere engagement fra brugerne. Lad os dykke ned i, hvordan du kan forvandle dit spil til en ydeevne-mester.

Indholdsfortegnelse

Hvorfor er Mobilspilsoptimering Vigtig?

Mobilspilsoptimering er ikke blot en god praksis; det er en nødvendighed. Mobiltelefoner og tablets varierer enormt i deres hardwarekapacitet, fra high-end flagskibe til budgetvenlige modeller. Et spil, der ikke er optimeret, vil enten ikke køre på ældre/svagere enheder, eller det vil give en utilfredsstillende oplevelse med lav billedhastighed, lange indlæsningstider og hurtigt drænet batteri. En god optimering sikrer en bredere målgruppe, forbedret brugerfastholdelse og bedre anmeldelser. Det handler om at maksimere spillets potentiale og sikre, at det når ud til så mange spillere som muligt med den bedst mulige oplevelse.

Scripting Optimering: Effektiv Kode

Koden i dit spil er fundamentet for dets ydeevne. Dårligt skrevet kode kan føre til unødvendig hukommelsesallokering og CPU-spidser, som direkte påvirker spillets flydende. Her er nogle nøgleområder inden for scripting, du bør fokusere på.

Ren Kode

Dit spil kan indeholde meget kode-redundans, hvilket kan påvirke ydeevnen. At holde din kode ren og organiseret kan øge effektiviteten. Undgå gentagelser, brug klare navnekonventioner, og strukturer din kode logisk. Dette gør ikke kun koden lettere at vedligeholde, men kan også optimere kompilering og udførelse.

Undgå Unødvendig Hukommelsesallokering

Hver gang et objekt oprettes, allokeres der hukommelse. Ofte opretter du objekter uden selv at vide det, og dette kan føre til 'Garbage Collection' (GC) spidser, som midlertidigt fryser spillet. At minimere hukommelsesallokering er en af de mest effektive måder at forbedre ydeevnen på.

Situation 1: String-konkatenation

I Unity refererer 'string' til en datatype, ikke et variabelnavn. Hvis du ofte 'debugger' log-indhold som f.eks.:

Debug.Log("hello" + " " + "world");

Denne kode vil oprette tre forskellige strenge og placere dem i heap-hukommelsen. Dette bør i stedet gøres som:

Debug.Log("hello world");

Ved at gøre dette opretter du kun én streng.

Situation 2: Brug Klasser og Strukturer Klogt

Valget mellem klasser og strukturer er afgørende for hukommelsesallokering og ydeevne. Når du opretter en struktur, allokeres dens hukommelse på stack'en, hvilket gør strukturer mere effektive end klasser, som allokeres på heap'en. Dette betyder, at strukturer er mere velegnede til funktioner, der kræver høj ydeevne og lavt hukommelsesforbrug. På grund af deres forskelle i hukommelsesallokering er strukturer generelt hurtigere end klasser. Hvis du arbejder med store mængder data, kan strukturer være mere effektive, fordi de ikke kræver overhead fra heap-hukommelsesallokering. Dog er der tilfælde, hvor klasser er hurtigere end strukturer. For eksempel, når man kopierer store objekter, kan klasser være mere effektive, fordi de kun kopierer en reference til objektet i stedet for selve objektet.

Hvornår skal man bruge Strukturer:
  • Når du har brug for at repræsentere simple datatyper (heltal, strenge, andre grundlæggende datatyper).
  • Når du arbejder med store datasæt (arrays eller lister), hvor ydeevne er kritisk.
  • Når du skal sende en lille mængde data til en metode, og du vil undgå overhead ved at sende en reference til en klasse.
Hvornår skal man bruge Klasser:
  • Bedst egnet til at repræsentere komplekse objekter (f.eks. biler eller personer) og til at oprette hierarkier af objekter med nedarvning.
  • Ideel til håndtering af store mængder data, f.eks. arbejde med databaser.
  • Nyttige, når du skal indkapsle funktionalitet og data sammen, hvilket giver organiseret og vedligeholdelsesvenlig kode.
  • Understøtter implementering af interfaces, hvilket forbedrer fleksibilitet og modularitet i din kode.
EgenskabStruktur (Struct)Klasse (Class)
HukommelsesallokeringStackHeap
Ydeevne for små dataGenerelt hurtigereGenerelt langsommere
KopieringKopierer hele værdienKopierer referencen
Egnet tilSimple datatyper, små datasæt, høj ydeevneKomplekse objekter, store datasæt, nedarvning

Situation 3: Brug C# Events i stedet for UnityEvents

UnityEvent skaber mindre garbage end C# events, hvis du tilføjer mere end to lyttere til det, men skaber ellers mere garbage. Det skaber garbage, når det 'dispatches' (første gang), hvor C# events ikke gør. Og det er mindst dobbelt så langsomt som C# events. For de fleste scenarier, hvor du kun har et par lyttere, vil C# events være det mere effektive valg.

Brug af Algoritmer

Den rette algoritme kan markant forbedre spillets ydeevne. Anvend algoritmer, når det er muligt, især til sortering, søgning og datahåndtering. En effektiv algoritme kan reducere beregningstiden fra sekunder til millisekunder, hvilket er afgørende for en flydende mobilspilsoplevelse.

Tekniske Optimeringer: Systemhåndtering

Udover kodeoptimering er der specifikke tekniske tilgange, der kan drastisk forbedre spillets ydeevne ved at ændre, hvordan ressourcer håndteres.

Object Pooling

For at forhindre 'Garbage Collector' (GC) problemer (CPU Spikes) i spil med mange objekter, der oprettes og ødelægges, kan en metode kaldet Object Pooling bruges. Object Pooling refererer til at oprette alle nødvendige objekter på forhånd og deaktivere/aktivere dem, når det er nødvendigt, i stedet for at instantiere (Instantiate()-funktionen) og ødelægge (Destroy()-funktionen) objekter under runtime. Disse objekter kan også oprettes på forhånd under en indlæsningsskærm og holdes skjult, indtil de er nødvendige. På denne måde vil de ikke forårsage ydeevneproblemer, når de oprettes under gameplay. Du kan skrive dit eget pooling-script eller bruge aktiver fra Unity Asset Store som f.eks. LeanPool.

Genanvendelig Scroll View

At oprette en scrollview med tusindvis af elementer (f.eks. 9999) forårsager en betydelig ydeevneforringelse for spillet. Derfor bruges en genanvendelig scrollview til at øge spillets ydeevne markant. I stedet for at oprette alle elementer i en scrollview, opretter en genanvendelig scrollview et bestemt antal elementer, der skal vises på skærmen, og genbruger dem, når brugeren scroller. 'Recyclable Scroll Rect - Optimized List/Grid View' er et eksempel på et aktiv, der kan hjælpe med dette.

Optimering af Assets Import: Effektiv Ressourcehåndtering

Spillets aktiver – teksturer, lyde, meshes og animationer – er ofte de største syndere, når det kommer til hukommelsesforbrug og indlæsningstider. Korrekte importindstillinger er afgørende.

Teksturer

Mest af din hukommelse vil sandsynligvis gå til teksturer, så importindstillingerne her er kritiske. Generelt skal du følge disse retningslinjer:

  • Sænk Max Size: Brug de minimale indstillinger, der giver visuelt acceptable resultater. Dette er ikke-destruktivt og kan hurtigt reducere din teksturhukommelse.
  • Brug 'Powers of Two' (POT): Unity kræver POT-teksturdimensioner til mobile teksturkomprimeringsformater (PVRCT eller ETC).
  • Atlas dine teksturer: At placere flere teksturer i en enkelt tekstur kan reducere 'draw calls' og fremskynde rendering. Brug Unity Sprite Atlas eller tredjeparts TexturePacker.
  • Slå 'Read/Write Enabled' fra: Når denne mulighed er aktiveret, oprettes en kopi i både CPU- og GPU-adresserbar hukommelse, hvilket fordobler teksturens hukommelsesforbrug. I de fleste tilfælde skal dette holdes deaktiveret.
  • Deaktiver unødvendige Mip Maps: Mip Maps er ikke nødvendige for teksturer, der forbliver i en konstant størrelse på skærmen, såsom 2D-sprites og UI-grafik (lad Mip Maps være aktiveret for 3D-modeller, der varierer deres afstand fra kameraet).
  • Komprimer Tekstur: For næsten alle mobile enheder i dag, bør formatet være RGBA Compressed ASTC. For ældre enheder kan du vælge ETC2 eller ETC komprimering. Player Settings giver en global standard for teksturkomprimering, der påvirker alle teksturer, medmindre de tilsidesættes.
KomprimeringsformatBeskrivelseAnbefales til
ASTC (Adaptive Scalable Texture Compression)Moderne format, god kvalitet og fleksibilitet.Nye og moderne mobile enheder.
ETC (Ericsson Texture Compression)Standardformat, bredt understøttet på Android.Ældre Android-enheder, generel kompatibilitet.
ETC2Forbedret ETC, understøtter alfa-kanaler.Nyere Android-enheder, når ASTC ikke er et valg.

Lyd

Lydfiler kan også være store hukommelsesforbrugere:

  • Aktiver altid 'Force to mono': Dette reducerer filstørrelsen, bruger mindre hukommelse og har mange andre fordele.
  • Reducer størrelsen på dine klip og hukommelsesforbrug med komprimering: Brug Vorbis til de fleste lyde (eller MP3 til lyde, der ikke er beregnet til at loope). Brug ADPCM til korte, ofte brugte lyde (f.eks. fodtrin, skud). Dette mindsker filerne sammenlignet med ukomprimeret PCM, men er hurtigt at dekode under afspilning.
  • Samplerate: Lydeffekter på mobile enheder bør være 22.050 Hz højst. Brug af lavere indstillinger har normalt minimal indvirkning på den endelige kvalitet; brug dine egne ører til at bedømme.
  • Indlæsningsstrategi: Indstillingen varierer efter klipstørrelse. Små klip (< 200 kb) skal 'Decompress on Load'. Dette medfører CPU-omkostninger og hukommelse ved at dekomprimere en lyd til rå 16-bit PCM-lyddata, så det er kun ønskeligt for korte lyde. Medium klip (>= 200 kb) skal forblive 'Compressed in Memory'. Store filer (baggrundsmusik) skal indstilles til 'Streaming', ellers vil hele aktivet blive indlæst i hukommelsen på én gang.

Meshes

Ligesom teksturer kan meshes forbruge overskydende hukommelse, hvis de ikke importeres forsigtigt. For at minimere meshes' hukommelsesforbrug:

  • Komprimer mesh: Aggressiv komprimering kan reducere diskplads (hukommelse under runtime påvirkes dog ikke). Bemærk, at mesh-kvantisering kan resultere i unøjagtighed, så eksperimenter med komprimeringsniveauer for at se, hvad der fungerer for dine modeller.
  • Deaktiver 'Read/Write': Aktivering af denne mulighed duplikerer meshen i hukommelsen, hvilket holder én kopi af meshen i systemhukommelsen og en anden i GPU-hukommelsen. I de fleste tilfælde bør du deaktivere den (i Unity 2019.2 og tidligere er denne mulighed afkrydset som standard).
  • Deaktiver 'Rigs' og 'BlendShapes': Hvis dit mesh ikke har brug for skelet- eller blendshape-animation, deaktiver disse muligheder, hvor det er muligt.
  • Deaktiver 'Normals' og 'Tangents': Hvis du er absolut sikker på, at meshens materiale ikke vil have brug for normals eller tangents, fjern markeringen af disse muligheder for ekstra besparelser.

Animationer

Animationer kan også optimeres via importindstillingerne for modellen. Du kan ændre egenskaber som rotationsfejl, positionsfejl og skalering for at reducere filstørrelsen. Husk dog, at disse parametre introducerer fejl i animationen, så du bør være forsigtig, når du justerer dem. Konsulter Unitys dokumentation for detaljer om komprimering og animation.

Tips og Tricks til Yderligere Optimering

Her er en række diverse, men effektive, optimeringsteknikker, der kan give dit spil den sidste finish.

Hold dig til Unity LTS-versioner

Du bør kun holde dig til Unity LTS (Long-term support) versioner. Versioner, der ikke understøtter LTS, har ofte uventede fejl og ustabilitet. LTS-versioner er mere stabile og modtager løbende opdateringer, hvilket sikrer en mere pålidelig udviklingsproces.

How do I reduce texture memory in Unity?
In general, try to follow these guidelines: Lower the Max Size: Use the minimum settings that produce visually acceptable results. This is non-destructive and can quickly reduce your texture memory. Use powers of two (POT): Unity requires POT texture dimensions for mobile texture compression formats (PVRCT or ETC).

Brug originale ukomprimerede WAV-filer som dine kildeaktiver

Hvis du bruger et komprimeret format (såsom MP3 eller Vorbis), vil Unity dekomprimere det og derefter rekomprimere det under byggetid. Dette resulterer i to tabsgivende passager, hvilket forringer den endelige kvalitet. Start med WAV for den bedste kvalitet.

Brug et minimum af Audio Source i dit spil

Hver aktiv audio source kræver CPU-ressourcer til afspilning, hvilket kan belaste enhedens behandlingskapacitet. Aktive audio sources forbruger hukommelse, og mobile enheder har typisk begrænset RAM. Overvej at genbruge audio sources eller kun aktivere dem, når det er absolut nødvendigt.

Tilpas Lineær vs. Gamma farverum

Gamma har bedre ydeevne (~10-30%) end Lineær. Dog er displayet en smule dårligere. Du kan finde denne mulighed i Player Setting -> Other Settings. Valget afhænger af dine visuelle præferencer og ydeevnekrav.

Prøv at bruge inkrementel GC (Garbage Collection)

Nogle gange kan aktivering af 'use incremental GC'-indstillingen forbedre spillets ydeevne, og nogle gange gør det ikke. Du bør se på profileren for at vurdere effekten. Du kan finde den i Player Setting. Inkrementel GC forsøger at sprede GC-arbejdet ud over flere frames for at undgå store 'spikes'.

Brug LOD-teknik (Level of Detail)

Level of Detail (LOD) er en teknik, der reducerer antallet af GPU-operationer, som Unity kræver for at rendere fjerne meshes. Når et GameObject i scenen er langt væk fra kameraet, ser du færre detaljer sammenlignet med, når GameObject er tæt på kameraet. Men som standard bruger Unity det samme antal trekanter til at rendere det ved begge afstande. Dette kan resultere i spildte GPU-operationer, som kan påvirke ydeevnen i din scene. LOD giver dig mulighed for at definere forskellige versioner af dit mesh med færre detaljer, der vises, når objektet er længere væk.

Bake Mesh (Mesh Baking)

Bake mesh er processen med at kombinere meshes for at reducere draw calls, hvilket også betyder at øge spillets ydeevne. Unity leverer ikke mesh baking som en indbygget funktion, men der er en del aktiver i butikken, der tilbyder mesh baking, såsom Mesh Baker eller ProBuilder. Dette er især nyttigt for statiske miljøer, hvor mange små objekter kan kombineres til færre, større meshes.

Falske Skygger (Fake Shadow)

Beregningen af skygger i Unity medfører en betydelig ydeevneomkostning, især på mobile enheder. Det er tilrådeligt at deaktivere skyggestøbning og -modtagelse, hvis det ikke er absolut nødvendigt, og erstatte dem med falske skygger som et alternativ for at forbedre ydeevnen. Du kan oprette falske skygger ved hjælp af en sløret tekstur anvendt på et simpelt mesh eller en quad under dine karakterer. Alternativt kan du oprette 'blob shadows' med brugerdefinerede shaders.

Pak Teksturer (Sprite Atlas)

Kombiner teksturer i et sprite atlas inden for den samme popup eller scene i Unity for at muliggøre batching draw calls. Dette vil hjælpe med at forbedre ydeevnen, selvom det kan øge spillets filstørrelse en smule. Sørg for at deaktivere 'tight packing', hvis du ikke ønsker forkert visning.

Aktiver GPU Instancing

GPU instancing er en 'draw call'-optimeringsmetode, der renderer flere kopier af et mesh med det samme materiale i et enkelt 'draw call'. Hver kopi af meshet kaldes en instans. Dette er nyttigt til at tegne ting, der vises flere gange i en scene, f.eks. træer eller buske. GPU instancing renderer identiske meshes i det samme 'draw call'. For at tilføje variation og reducere udseendet af gentagelse kan hver instans have forskellige egenskaber, såsom Farve eller Skala.

Deaktiver Vsync

Aktivering af Vsync i mobilspil kan forårsage lag, hurtigere batteridræn og også begrænse billedhastigheden til skærmens opdateringshastighed. For de fleste mobilspil er det bedst at deaktivere Vsync og lade spillet køre med så høj billedhastighed som muligt (eller en fastsat, optimeret billedhastighed).

Vælg Egnet Grafik API

I Player Settings kan du kontrollere listen over grafik-API'er, der understøttes af den aktuelle version af Unity, ved at fravælge 'Auto Graphics API' og klikke på plus-tegnet for at se alle API'er. For Android er der 3 API-grafikmuligheder: GLES2, GLES3 og Vulkan baseret på Unity-versionen. GLES3 er det bedste valg for populære mobile enheder, som du ikke bør fjerne. Hvis du vil målrette mod ældre enheder, bør du have GLES2. Vulkan er en god mulighed for moderne enheder, men nogle gange forårsager det nedbrud og lag for lavere enheder. Min anbefaling er at bruge GLES2 og GLES3 til optimering, da de dækker et bredt spektrum af enheder.

Ofte Stillede Spørgsmål (FAQ)

Hvad er 'Garbage Collection' (GC) og hvorfor er det et problem?

'Garbage Collection' er en proces, hvor Unity (eller .NET runtime) automatisk frigiver hukommelse, der ikke længere er i brug. Problemet opstår, når der oprettes mange nye objekter i hurtig rækkefølge (f.eks. i en 'Update'-funktion), hvilket tvinger GC til at køre oftere. Hver gang GC kører, kan det medføre en kort pause eller 'spik' i spillets udførelse, hvilket resulterer i hakken eller frysning, der forringer brugeroplevelsen. Optimeringsmålene er at minimere hukommelsesallokering og dermed reducere behovet for GC.

Hvorfor er det vigtigt at reducere 'Draw Calls'?

En 'draw call' er en instruktion fra CPU'en til GPU'en om at tegne et sæt trekanter. Hver 'draw call' har en vis overhead for CPU'en. På mobile enheder, hvor CPU'en ofte er en flaskehals, kan et højt antal 'draw calls' føre til dårlig ydeevne. Ved at reducere antallet af 'draw calls' (f.eks. ved at 'batche' objekter, bruge sprite atlases eller 'mesh baking'), kan du aflaste CPU'en og forbedre billedhastigheden.

Hvad er forskellen på stack og heap hukommelse?

Stack-hukommelsen er et hurtigt og organiseret område, hvor lokale variabler og funktionskald gemmes. Data på stack'en tildeles og frigives automatisk og meget hurtigt. Heap-hukommelsen er et større, mindre organiseret område, hvor objekter med længere levetid gemmes. Allokering på heap'en er langsommere og kræver 'Garbage Collection' for at rydde op. Strukturer gemmes typisk på stack'en, mens klasser gemmes på heap'en, hvilket forklarer deres forskellige ydeevnekarakteristika.

Hvorfor skal jeg undgå at bruge Instantiate() og Destroy() for ofte?

Instantiate() og Destroy() er dyre operationer, fordi de involverer allokering og deallokering af hukommelse på heap'en. Dette fører til hyppige 'Garbage Collection'-kørsler, som kan forårsage 'spikes' i spillets billedhastighed. Ved at bruge 'Object Pooling' undgår man disse omkostninger ved at genbruge objekter i stedet for at oprette og ødelægge dem løbende, hvilket resulterer i en meget mere flydende ydeevne.

Hvad er ASTC og ETC komprimering?

ASTC (Adaptive Scalable Texture Compression) og ETC (Ericsson Texture Compression) er to populære komprimeringsformater for teksturer på mobile enheder. ASTC er et nyere, mere avanceret format, der tilbyder fremragende billedkvalitet og fleksibilitet med hensyn til komprimeringsforhold. Det er ideelt til moderne enheder. ETC er et ældre, men bredt understøttet format, især på Android-enheder. Mens ETC generelt er mindre effektivt end ASTC med hensyn til kvalitet og kompressionsforhold, er det et sikkert valg for at sikre kompatibilitet med et bredere udvalg af ældre enheder.

Konklusion

Optimering af mobilspil i Unity er en løbende proces og en kunstform, der kræver opmærksomhed på detaljer i alle faser af udviklingen. Ved at implementere de strategier og teknikker, der er beskrevet i denne artikel – lige fra omhyggelig kodeoptimering og smart asset-håndtering til udnyttelse af avancerede Unity-funktioner – kan du markant forbedre dit spils ydeevne, reducere hukommelsesforbrug og levere en uovertruffen spiloplevelse til dine spillere. Husk, at et optimeret spil ikke kun kører bedre, men også appellerer til et bredere publikum og opnår større succes på det konkurrenceprægede mobilmarked. God optimeringslyst!

Hvis du vil læse andre artikler, der ligner Optimal Ydeevne: Guide til Mobilspilsoptimering i Unity, kan du besøge kategorien Teknologi.

Go up