Can a material property block be used to change / overwrite material settings?

Unity Mobilspilsoptimering: Din Komplette Guide

22/10/2025

Rating: 4.74 (7200 votes)

I den hastigt voksende verden af mobilspil er ydeevne ikke bare en fordel – det er en nødvendighed. En flydende og responsiv spiloplevelse er afgørende for at fastholde spillere og sikre succes. Men mobilplatforme, med deres varierende hardware og begrænsede ressourcer, præsenterer unikke udfordringer for spiludviklere. At forstå, hvordan man bedst optimerer sit Unity-spil, kan være forskellen mellem et hit og en glemt titel.

What is a static property in Unity?
Set the Static property on non-moving objects to allow internal optimizations like static batching A technique Unity uses to draw GameObjects on the screen that combines static (non-moving) GameObjects into big Meshes, and renders them in a faster way.

Denne artikel dykker ned i de vigtigste aspekter af Unity-mobilspilsoptimering, fra grafikydeevne til CPU-belastning og effektiv ressourcehåndtering. Vi vil give dig praktiske strategier og indsigt i de bedste praksisser, der kan hjælpe dig med at frigøre det fulde potentiale i dine mobilspil, uanset om du udvikler til iOS eller Android.

Indholdsfortegnelse

Forstå Mobilplatformens Udfordringer

Mobiltelefoner og tablets kommer i et utal af konfigurationer, fra high-end flagskibe til budgetvenlige enheder. Denne variation betyder, at et spil, der kører problemfrit på én enhed, kan hakke og fryse på en anden. Den nemmeste måde at skalere et spil på er at sikre, at det kører acceptabelt på en baseline-konfiguration, og derefter tilføje flere visuelle elementer ('eye-candy') på højere ydende enheder. Dette kan inkludere højere opløsning, post-processing effekter, MSAA (Multi-Sample Anti-Aliasing), anisotropisk filtrering, mere komplekse shaders og højere partikeltæthed.

Mobil-GPU'er har markante begrænsninger i forhold til varmeudvikling, strømforbrug og fysisk størrelse, hvilket direkte påvirker deres ydeevne sammenlignet med desktop-GPU'er. De har typisk betydeligt mindre båndbredde, lavere ALU-ydeevne (Arithmetic Logic Unit) og mindre teksturkraft. Mobil-GPU-arkitekturer er også designet til at minimere båndbreddeforbrug og strømforbrug, hvilket kræver en bevidst optimeringsstrategi fra udviklerens side.

Unity er optimeret til OpenGL ES 2.0 og bruger GLSL ES (ligner HLSL) som shading-sprog. Indbyggede shaders er ofte skrevet i HLSL (også kendt som Cg) og bliver tværkompileret til GLSL ES for mobilplatforme. Når du bruger typer som float, half eller fixed i HLSL, oversættes de til highp, mediump eller lowp præcisionskvalifikatorer i GLSL ES, hvilket er afgørende for ydeevnen på mobile enheder.

Fokus på GPU-Optimering

Grafikydeevne på mobile enheder er ofte begrænset af fillrate, pixel- og geometrisk kompleksitet (antal vertexer). Alle tre kan reduceres ved at frasortere flere renderere. Occlusion culling, hvor Unity automatisk skjuler objekter uden for kameraets synsfelt, kan være en stor hjælp her. På mobile enheder er du primært begrænset af fillrate, som er produktet af skærmpixels, shader-kompleksitet og overdraw. Overkomplekse shaders er den mest almindelige årsag til ydeevneproblemer.

Shader-Optimering: Mindre Er Mere

For at optimere shaders bør du:

  • Bruge de indbyggede 'Mobile' shaders, der følger med Unity, eller designe dine egne, men hold dem så enkle som muligt.
  • Hvis muligt, forenkle dine pixel-shaders ved at flytte kode til vertex-shaderen.
  • Undgå alpha-testende shaders, medmindre det er absolut nødvendigt; brug i stedet alpha-blended versioner.
  • Undgå dyre matematiske funktioner i shader-kode som pow, exp, log, cos, sin og tan. Overvej at bruge forudberegnede lookup-teksturer i stedet.
  • Vælg den lavest mulige talpræcision (float, half, fixed i Cg) for den bedste ydeevne.

Hvis spillet kører hurtigere, når du reducerer teksturkvaliteten i kvalitetsindstillingerne, er du sandsynligvis begrænset af hukommelsesbåndbredde. Løsningen er at komprimere teksturer, bruge mipmaps (mindre versioner af teksturer til objekter længere væk), reducere teksturstørrelsen og så videre.

Level of Detail (LOD) er en anden effektiv teknik, hvor objekter gøres simplere eller elimineres helt, når de bevæger sig længere væk fra kameraet. Dette reducerer både geometrisk kompleksitet og fillrate.

God GPU-Praksis

  • Hold antallet af materialer så lavt som muligt. Dette gør det lettere for Unity at batch-tegne objekter.
  • Brug teksturatlaser (store billeder, der indeholder en samling af underbilleder) i stedet for mange individuelle teksturer. Disse er hurtigere at indlæse, kræver færre tilstandsændringer og er venlige over for batching.
  • Brug Renderer.sharedMaterial i stedet for Renderer.material, hvis du bruger teksturatlaser og delte materialer.
  • Forward-rendered pixel-lys er dyre. Brug lys-mapping (lightmapping) i stedet for realtidslys. Juster antallet af pixel-lys i kvalitetsindstillingerne. Typisk bør kun det retningsbestemte lys være per pixel, alt andet per vertex. Eksperimenter med 'Render Mode' for lys i kvalitetsindstillingerne for at opnå den korrekte prioritet.
  • Undgå 'Cutout' (alpha test) shaders, medmindre det er absolut nødvendigt.
  • Hold 'Transparent' (alpha blend) skærmdækning på et minimum.
  • Forsøg at undgå situationer, hvor flere lys belyser et givent objekt.
  • Forsøg at reducere det samlede antal shader-passes (skygger, pixel-lys, refleksioner).
  • Renderingsrækkefølge er kritisk: Generelt bør fuldt opake objekter tegnes cirka forfra-tilbage, alpha-testede objekter cirka forfra-tilbage, skybox, og derefter alpha-blended objekter (bagfra-frem, hvis nødvendigt).
  • Post-processing er dyrt på mobile enheder; brug det med omhu.
  • Partikler: Reducer overdraw, og brug de simpleste mulige shaders.
  • Brug dobbeltbuffer for meshes, der modificeres hver frame:
    void Update () { // flip between meshes bufferMesh = on ? meshA: meshB; on = !on; bufferMesh.vertices = vertices; // modification to mesh meshFilter.sharedMesh = bufferMesh; }

CPU-Ydeevne og God Praksis

Det er ofte tilfældet, at spil er begrænset af GPU'en på pixelbehandling, hvilket resulterer i ubrugt CPU-kraft, især på multicore mobile CPU'er. Det er derfor ofte fornuftigt at flytte noget arbejde fra GPU'en til CPU'en. Unity gør dette for mesh skinning, batching af små objekter og partikelgeometri-opdateringer.

Disse teknikker skal dog bruges med omhu og ikke blindt. Hvis du ikke er begrænset af draw calls, kan batching faktisk være dårligere for ydeevnen, da det gør culling mindre effektivt og får flere objekter til at blive påvirket af lys.

God CPU-Praksis

  • FindObjectsOfType (og Unitys getter-properties generelt) er meget langsomme, så brug dem med omtanke. Cache referencer, hvor det er muligt.
  • Sæt den Static property på ikke-bevægelige objekter for at muliggøre interne optimeringer som static batching. Dette reducerer antallet af draw calls betydeligt.
  • Brug mange CPU-cyklusser til at udføre occlusion culling og bedre sortering (for at drage fordel af Early Z-cull).

Fysik: En Tung Byrde for CPU'en

Fysikberegninger kan være meget CPU-tunge. De kan profileres via Unity Editor-profileren. Hvis fysikken ser ud til at tage for meget CPU-tid, kan du justere følgende:

  • Juster Time.fixedDeltaTime (i Project Settings -> Time) til at være så høj, som du kan slippe af sted med. Hvis dit spil er langsomt bevægende, har du sandsynligvis brug for færre faste opdateringer end spil med hurtig action. Hurtige spil vil kræve hyppigere beregninger, og dermed skal fixedDeltaTime være lavere, ellers kan en kollision fejle.
  • Juster Physics.solverIterationCount (i Physics settings). Et lavere antal iterationer kan forbedre ydeevnen på bekostning af præcision.
  • Brug så få 'Cloth'-objekter som muligt.
  • Brug Rigidbodies til bevægelige objekter, der skal interagere med fysik.
  • Brug primitive colliders (kasser, kugler, kapsler) frem for mesh colliders, når det er muligt. Primitive colliders er langt mere effektive at beregne.
  • Flyt aldrig en statisk collider (dvs. en collider uden en Rigidbody), da det forårsager et stort ydeevnetab. Dette vises i Profileren som 'Static Collider.Move', men den faktiske behandling sker i 'Physics.Simulate'. Hvis det er nødvendigt at flytte en collider, skal du tilføje en Rigidbody og sætte isKinematic til true.

Effektiv Ressourcehåndtering

Korrekt ressourcehåndtering er afgørende for mobilspil, især med hensyn til hukommelsesforbrug og indlæsningstider.

Asset Bundles

Asset Bundles er en effektiv måde at organisere og indlæse spilindhold dynamisk. De kan cachelagres på en enhed til en vis grænse. De oprettes ved hjælp af Editor API'en og indlæses via WWW.LoadFromCacheOrDownload eller som en ressource (AssetBundle.CreateFromMemory eller AssetBundle.CreateFromFile).

Afhængig af behov kan du vælge at aflæse Asset Bundles med AssetBundle.Unload(true) for at fjerne både bundlen og de indlæste aktiver, eller AssetBundle.Unload(false) for kun at aflæse bundlen, men beholde de indlæste aktiver i hukommelsen. Husk at fjerne referencer til aktiver, du ikke længere har brug for, da offentlige og statiske variabler aldrig bliver garbage collected.

Resources.UnloadUnusedAssets() aflæser alle aktiver, der ikke længere er refereret i scenen. Resources.UnloadAsset() aflæser et specifikt aktiv fra hukommelsen, som kan genindlæses fra disk, hvis nødvendigt.

Når det kommer til samtidige downloads af Asset Bundles, er der ingen specifik Unity-begrænsning. Operativsystemet afgør, hvor mange tråde der oprettes til downloads. Vær dog opmærksom på enhedens samlede båndbredde og mængden af ledig hukommelse, da hver samtidig download allokerer sin egen midlertidige buffer.

What is a static property in Unity?
Set the Static property on non-moving objects to allow internal optimizations like static batching A technique Unity uses to draw GameObjects on the screen that combines static (non-moving) GameObjects into big Meshes, and renders them in a faster way.

Ressourcer

Aktiver skal genkendes af Unity for at blive inkluderet i et build. Tilføj .bytes filtypenavnet til rå bytes, du ønsker, at Unity skal genkende som binær data. Tilføj .txt filtypenavnet til tekstfiler, du ønsker, at Unity skal genkende som tekstaktiver.

Aktiver i 'Resources' mappen konverteres til et platformsformat ved build-tidspunktet. Resources.Load() er en synkron operation, der kan forårsage hakken, hvis den bruges til store aktiver under gameplay.

Hvad Er En "Static" Egenskab i Unity?

I Unity er "Static" en meget vigtig egenskab, du kan tildele et GameObject i Inspector-vinduet. Når et objekt er markeret som "Static", fortæller du Unity, at dette objekt ikke vil bevæge sig, skaleres eller roteres under kørsel. Denne information gør det muligt for Unity at udføre en række kraftige optimeringer, der ellers ikke ville være mulige.

De primære fordele ved at markere objekter som statiske inkluderer:

  • Static Batching: Unity kan kombinere geometrien fra flere statiske objekter til en enkelt stor mesh. Dette reducerer antallet af 'draw calls' til GPU'en dramatisk, hvilket er en af de største flaskehalse i spilrendering. Færre draw calls betyder bedre ydeevne.
  • Occlusion Culling: Statiske objekter bruges til at forudberegne, hvilke dele af scenen der er synlige fra forskellige synspunkter. Dette gør det muligt for Unity at undgå at tegne objekter, der er skjult bag andre statiske objekter, hvilket yderligere reducerer renderingsoverhead.
  • Lightmapping: Statiske objekter kan bage lysinformation (skygger og indirekte lys) direkte ind i teksturer, kendt som lightmaps. Dette eliminerer behovet for dyre realtidslys og skyggeberegninger under kørsel, hvilket forbedrer ydeevnen markant.
  • Navigation Meshes: Statiske objekter bruges som grundlag for at bage navigationsmeshes, som AI-agenter kan bruge til at finde stier i spilverdenen.

Kort sagt, hvis et objekt ikke bevæger sig under gameplay (f.eks. vægge, gulve, træer, bygninger), bør du næsten altid markere det som "Static". Det er en af de mest effektive måder at forbedre dit spils ydeevne på, især på mobile enheder.

Kan MaterialPropertyBlock Ændre Materialeindstillinger?

Ja, en MaterialPropertyBlock kan absolut bruges til at ændre og overskrive materialeindstillinger for individuelle Renderer instanser. Dette er en utrolig kraftfuld optimeringsteknik i Unity, især når du skal variere udseendet af mange objekter, der deler det samme materiale, uden at bryde batching.

Normalt, hvis du ændrer en egenskab på et materiale via renderer.material.color = newColor;, vil Unity implicit oprette en ny instans af materialet for den pågældende renderer. Hvis du har hundredevis af objekter, der deler det samme materiale, men du ønsker at give dem en unik farve, ville dette skabe hundredevis af nye materialinstanser. Dette ville øge hukommelsesforbruget markant og, endnu vigtigere, forhindre Unity i at batch-tegne disse objekter, hvilket fører til et stort fald i ydeevnen.

MaterialPropertyBlock løser dette problem. Det er en simpel klasse, der indeholder en samling af materialeegenskaber (farver, teksturer, floats, vektorer). Du opretter en instans af MaterialPropertyBlock, sætter de ønskede egenskaber på den, og anvender den derefter på en Renderer ved hjælp af renderer.SetPropertyBlock(materialPropertyBlock);.

Fordelene ved at bruge MaterialPropertyBlock inkluderer:

  • Bevarer Batching: Objekter kan fortsat blive statisk eller dynamisk batchet, selvom de har forskellige farver eller andre egenskaber. Dette reducerer draw calls betydeligt.
  • Hukommelsesbesparelser: Du undgår at oprette mange unikke materialinstanser, hvilket sparer hukommelse.
  • Fleksibilitet: Giver dig mulighed for at tilføje visuel variation til objekter, der deler det samme materiale, uden at gå på kompromis med ydeevnen.

Det er et essentielt værktøj i optimeringsværktøjskassen for Unity-udviklere, der ønsker at opnå den bedst mulige ydeevne og visuelle variation.

Almindelige Fælder og Fejlfinding

Selv med den bedste intention kan optimeringsprocessen være fyldt med faldgruber. Her er en tjekliste over almindelige problemer og løsninger:

  • Teksturer uden korrekt komprimering: Sørg for at komprimere teksturer, medmindre du er sikker på, at du ikke bør. Brug ETC/RGBA16 som standard til Android (kan justeres afhængigt af GPU-producenten). PVRTC er standard for iOS. Alpha-teksturer kan bruge to ETC-filer.
  • Teksturer med 'Get/Set pixels' aktiveret: Dette fordobler hukommelsesforbruget. Deaktiver det, medmindre 'Get/Set' er absolut nødvendigt for runtime-operationer.
  • Teksturer indlæst fra JPEG/PNGs under kørsel: Disse vil blive dekomprimeret i hukommelsen, hvilket kan være hukommelsestungt. Forudkomprimer teksturer, hvor det er muligt.
  • Store MP3-filer markeret som 'decompress on load': De kan forbruge betydelige mængder hukommelse. Overvej at streame dem eller komprimere dem yderligere.
  • Additiv sceneindlæsning: Kan føre til akkumulering af ubrugte aktiver i hukommelsen. Sørg for at rydde op med Resources.UnloadUnusedAssets().
  • Ubrugte aktiver, der forbliver i hukommelsen: Husk at fjerne referencer til aktiver, der ikke længere er nødvendige, især i offentlige og statiske variabler.
  • Tilfældige nedbrud: Hvis spillet tilfældigt crasher, prøv at teste på et udviklingskit eller en enhed med rigelig hukommelse (f.eks. iPad 3 med 2 GB RAM). På iOS kan 'Fast script call' og 'stripping' føre til tilfældige nedbrud. Prøv at deaktivere dem under fejlfinding.

Ofte Stillede Spørgsmål

Hvad er 'overdraw' og hvordan undgår jeg det?

Overdraw er, når pixels tegnes flere gange på samme sted på skærmen. Dette sker, når gennemsigtige eller semi-gennemsigtige objekter overlapper hinanden, eller når objekter tegnes i den forkerte rækkefølge. Det belaster GPU'ens fillrate. For at undgå det, minimer gennemsigtige områder, optimer renderingrækkefølgen (opake objekter forfra-bagud, gennemsigtige bagfra-fremad) og reducer antallet af partikler og post-processing effekter, der kan forårsage overdreven overdraw.

Hvorfor er 'draw calls' så vigtige at reducere?

En 'draw call' er en instruktion fra CPU'en til GPU'en om at tegne noget. Hver draw call medfører en vis overhead for CPU'en. Hvis du har mange små objekter, der hver især kræver deres egen draw call, kan CPU'en blive en flaskehals. Ved at reducere antallet af draw calls (f.eks. gennem batching af statiske objekter eller ved at bruge teksturatlaser), kan du frigøre CPU-ressourcer og forbedre ydeevnen markant.

Hvordan profilerer jeg mit spil i Unity?

Unity Editor har en indbygget Profiler, som er et uvurderligt værktøj. Den viser, hvor meget tid der bruges på forskellige områder af dit spil, såsom rendering, animation, fysik og scripts. For at få de mest nøjagtige resultater skal du profilere direkte på en fysisk mobilenhed, ikke kun i Editoren, da ydeevnen kan variere betydeligt.

Er der forskel på optimering til iOS og Android?

Ja, der er forskelle, primært på grund af GPU-arkitekturer og platformspecifikke komprimeringsformater. iOS-enheder bruger typisk PowerVR GPU'er (tile-based, deferred rendering), hvor mipmaps er mindre kritiske, og antialiasing er lettere at opnå. Android har et bredere udvalg af GPU-arkitekturer (PowerVR, Tegra, Adreno, Mali), hvilket gør platformspecifik teksturkomprimering (f.eks. ETC) mere relevant. Test altid på de specifikke målenheder.

Konklusion

Optimering af mobilspil i Unity er en løbende proces, der kræver en dyb forståelse af både Unity-motoren og mobilhardwarens begrænsninger. Ved at fokusere på effektiv GPU- og CPU-udnyttelse, intelligent ressourcehåndtering og ved at anvende værktøjer som 'Static' egenskaben og 'MaterialPropertyBlock', kan du skabe spil, der ikke kun ser fantastiske ud, men også kører flydende på en bred vifte af mobile enheder. Husk at profilere dit spil regelmæssigt på faktiske enheder for at identificere og løse ydeevneflaskehalse tidligt i udviklingscyklussen. Med disse strategier er du godt rustet til at levere en enestående spiloplevelse til dine spillere.

Hvis du vil læse andre artikler, der ligner Unity Mobilspilsoptimering: Din Komplette Guide, kan du besøge kategorien Teknologi.

Go up