Jeg har søgt på internettet for at finde en effektiv måde at oprette et proceduremæssigt tilemap uden at oprette et GameObject pr. Flise. Alle TileMap-tutorials, jeg har fundet, opretter fliser ved at oprette hundreder af GameObjects. Således udvides hierarkiet i Unity uventet.
Jeg er ret sikker på, at dette ikke er den “rigtige” måde at gøre det på. Især efter at have set de nye Unity 2D-værktøjer, der understøtter tilemaps. Unity gjorde det sådan, du kan oprette fliser i “et” spilobjekt, ikke for hver flise.
Så hvordan gør jeg det på den rigtige og effektive måde?
Kommentarer
- Du ‘ har krydset dette til to SE-websteder. Vælg en.
- Hvad ‘ er din specifikke bekymring med at oprette et stort antal GameObjects? Hvis det ‘ bare er hierarkisk rod, er der nemme måder at rette op på. Enhed ‘ s batching skal alligevel kombinere lignende fliser i en enkelt batch, så der er usandsynligt, at ‘ sandsynligvis ikke er en stor trækopkrævning for at gøre det på denne måde. Minimering af offscreen-fliser og tid brugt i fliseopdateringsfunktioner er også begge løse problemer. Har du profileret dit spil og identificeret et specifi c flaskehals, du ‘ forsøger at løse?
- @DMGregory Nå, hvis vi tænker på 100 * 100 kort på skærmen (hvis vi antager, at vi zoomet ud for at se hele kort), vil det udgøre 10.000 spilobjekter i scenen. Det betyder også 10.000 unødvendig transformeringskomponent. Jeg ved ‘ ikke engang, om enhed kan understøtte 10.000 objekt i hieararkivinduet. Jeg ved, at det fryser efter par hundrede.
Svar
Her er hvad jeg er opmærksom på:
Mulighed 1. GameObject pr. flise. Det er ikke helt forfærdeligt i visse tilfælde. Afhængigt af dine behov kan det fungere .. godt nok.
Mulighed 2. En enkelt firkant eller et plan, der henviser til en tekstur, du opretter ved kørselstid. Brug i det væsentlige din flise-atlas-tekstur til at “male” dit kort som en ny tekstur. Afhængigt af størrelsen på dit kort vil du naturligvis måske have flere firhjulinger / plan, der hver repræsenterer dele af dit kort.
Valgmulighed 3. Opret dit eget maske. Dette ville mere end sandsynligt være den metode, du mest kan lide, når du først er implementeret. Det vil give dig masser af fleksibilitet og sandsynligvis den højeste ydeevne. Du opretter i det væsentlige en firkant pr. Flise og indstiller hver toppunkt-UV til at kortlægge til fliserne i dit fliseatlas.
For Option 2, I ” d foreslår at se denne videoserie af quill18creates: 3D TileMap tutorial-serie af quill18creates
For Option 3 er dette min kode med tweaks, så det er muligvis ikke perfekt:
//For this, your GameObject this script is attached to would have a //Transform Component, a Mesh Filter Component, and a Mesh Renderer //component. You will also need to assign your texture atlas / material //to it. void Start() { meshFilter = GetComponent<MeshFilter>(); BuildMesh(); } public void BuildMesh() { int numTiles = mapSizeX * mapSizeY; int numTriangles = numTiles * 6; int numVerts = numTiles * 4; Vector3[] vertices = new Vector3[numVerts]; UVArray = new Vector2[numVerts]; int x, y, iVertCount = 0; for (x = 0; x < mapSizeX; x++) { for (y = 0; y < mapSizeY; y++) { vertices[iVertCount + 0] = new Vector3(x, y, 0); vertices[iVertCount + 1] = new Vector3(x + 1, y, 0); vertices[iVertCount + 2] = new Vector3(x + 1, y + 1, 0); vertices[iVertCount + 3] = new Vector3(x, y + 1, 0); iVertCount += 4; } } int[] triangles = new int[numTriangles]; int iIndexCount = 0; iVertCount = 0; for (int i = 0; i < numTiles; i++) { triangles[iIndexCount + 0] += (iVertCount + 0); triangles[iIndexCount + 1] += (iVertCount + 1); triangles[iIndexCount + 2] += (iVertCount + 2); triangles[iIndexCount + 3] += (iVertCount + 0); triangles[iIndexCount + 4] += (iVertCount + 2); triangles[iIndexCount + 5] += (iVertCount + 3); iVertCount += 4; iIndexCount += 6; } mesh = new Mesh(); //mesh.MarkDynamic(); if you intend to change the vertices a lot, this will help. mesh.vertices = vertices; mesh.triangles = triangles; meshFilter.mesh = mesh; UpdateMesh(); //I put this in a separate method for my own purposes. } //Note, the example UV entries I have are assuming a tile atlas //with 16 total tiles in a 4x4 grid. public void UpdateMesh() { int iVertCount = 0; for (int x = 0; x < mapSizeX; x++) { for (int y = 0; y < mapSizeY; y++) { UVArray[iVertCount + 0] = new Vector2(0, 0); //Top left of tile in atlas UVArray[iVertCount + 1] = new Vector2(.25f, 0); //Top right of tile in atlas UVArray[iVertCount + 2] = new Vector2(.25f, .25f); //Bottom right of tile in atlas UVArray[iVertCount + 3] = new Vector2(0, .25f); //Bottom left of tile in atlas iVertCount += 4; } } meshFilter.mesh.uv = UVArray; }
Kommentarer
- Dine svar hjalp mig tilbage i dage. Nu kigger jeg gennem mine gamle spørgsmål, og jeg ‘ har indset, at jeg ‘ aldrig har kontrolleret dette svar som accepteret. Undskyld for en evig forsinket godkendelse ^^ Tak for svaret.
Svar
Som dig (jeg tror ) hentydet til, har Unitys køreplan planer for en tilemap-editor. Jeg ser frem til det, for lige nu er det lidt forvirrende, hvordan man fortsætter.
I mellemtiden er den bedste tilgang jeg “Jeg ser er at lave dit kort i Tiled og derefter bruge X-UniTMX til at importere det til Unity. Det er åbenbart, at “ikke proceduremæssig generering; jeg kunne forestille mig, at du ville bruge den samme teknik som X-UniTMX bruger til at skabe nettet.
Svar
Du kan bare få fliserne oprettet dybere i hierarkiet og lukke den mappe og ikke være generet. Hvad du også kan gøre er at skjule dine spilobjekter fra hierarkiet `myTile.hideFlags = HideFlags. HideInHierarchy “ikke sikker på, hvor meget ydeevne der opnås.
At vise 100×100 teksturer på skærmen er aldrig en god idé at tegne teksturer er mere tungt end at tegne polygoner alligevel. Hvis du har brug for at zoome så langt ud, har du det bedre med større teksturer. Det samme gælder for at blive zoomet ind, du skal ikke tegne de teksturer, der ikke behøver at blive tegnet.
Hvad jeg normalt gør (jeg er ikke en Unity-fyr) er at oprette en klasse til et kort og bruge et 2-dimensionelt array til at holde alle dine fliser. Dette array kan være simpelthen af ints eller en Tile-klasse med et par ints, der henviser til dine teksturer, flisetype, objekter osv. Derefter tegner man det som følger:
for (int y = 0; y < mapHeight; y++) { for(int x = 0; x < mapHeight; x++) { Graphics.DrawTexture(new Rect(x * tileWidth, y * tileHeight, tileWidth, tileHeigt), tileTexture); } }
Tegningsmetoden, jeg bruger, ser ud til at være til tegning af en GUI, men kan være perfekt egnet til opgaven. Ellers skal du grave i sprite manager og finde en måde der fungerer med denne metode.
Du kan bruge en ordbog til teksturreference som int 1
i din fliseklasse henviser til en vis struktur og int 2
henviser til en anden.På den linje, du tegner din tekstur, bruger du din ordbog til at give det rigtige teksturobjekt. På denne måde skal det ikke skabe et GameObject og dermed ikke skabe alle unødvendige omkostninger.
Du kan gøre det samme for stort set alt, hvad der ikke har brug for kontrolniveauet for et GameObject. Husk dog, på denne måde tegner det alle fliser på dit kort, det sandsynligvis ikke automatisk sletter objekterne, som jeg tror, at enhed gør med spilgenstande. Men det er meget let at tegne det, der skal være på skærmen. Du kender skærm / visningsstørrelse, kameraposition og flisestørrelse. Noget simpelt matematik skal tegne præcis, hvad der er nødvendigt.
Enhed er stadig en 3D-motor. Den understøtter bare 2D på en 3D-måde. Men du kan stort set gøre det samme for quads / masker med teksturer et ortografisk kamera. Det er ret billigt at tegne de nødvendige masker.
Svar
Som nogen, der arbejder på voxel / blokbaseret projekt , Jeg kan ikke lade være med at tænke på bare at bruge den samme tilgang, kun i 2D. Du kan opbygge et gitterlignende maske procedurelt og tildele rigtige koordinater til flisevisualiteter i dit teksturatlas til UV-kanal. I 3D skal du gøre meget mere job end dette for at have høj ydeevne, men i 2D er det meget sandsynligt, det er virkelig nok.
Svar
Du kan altid bruge LeanPool . Det er et gratis aktiv i aktivbutikken. Det samler objekt for dig. Derefter kan du foretage et simpelt aflæsningssystem omkring kameraets visning, der gyder / de gyder fliser spilobjekter, når de kommer ind / ud af kameraets visning. Jeg er ikke sikker på, hvor stort dit tilemap vil være, men Unity kan håndtere en hel del spilobjekter. LeanPool har benchmarkscener i Unity, hvor du kan gyde / de gyde tusind objekter med kassekollisionskomponenter, og jeg tror muligvis også en gengivelseskomponent på hver enkelt, og det gør det meget hurtigt.
https://gamedevacademy.org/how-to-script-a-2d-tile-map-in-unity3d/
Her er et link, der viser dig et eksempel på brug af LeanPool med et tilemap.