Enhetsprosessuell TileMap-generering uten å lage gameobject per flis

Jeg har søkt på internett for å finne en effektiv måte å lage et prosessuelt tilemap uten å lage et GameObject per flis. Alle TileMap-opplæringene jeg har funnet, lager fliser ved å lage hundrevis av GameObjects. Dermed utvides hierarkiet i Unity uventet.

Jeg er ganske sikker på at dette ikke er den «riktige» måten å gjøre det på. Spesielt etter å ha sett de nye Unity 2D-verktøyene som støtter tilemaps. Unity gjorde det slik, du kan lage fliser i «ett» spillobjekt, ikke for hver brikke.

Så hvordan gjør jeg det på riktig og effektiv måte?

Kommentarer

  • Du ‘ har krysset dette på to SE-nettsteder. Velg en.
  • Hva ‘ er din spesielle bekymring med å lage et stort antall GameObjects? Hvis det ‘ bare er hierarkisk rot, er det enkle måter å fikse det på. Enhet ‘ s batching burde kombinere lignende fliser i en enkelt batch uansett, så det er usannsynlig at det er ‘ som er en stor straffestrekning for å gjøre det på denne måten. tid brukt på flisoppdateringsfunksjoner er begge løsbare problemer også. Har du profilert spillet ditt og identifisert en spesifikasjon c flaskehals du ‘ prøver å løse?
  • @DMGregory Vel hvis vi tenker på 100 * 100 kart på skjermen (hvis vi antar at vi zoomet ut for å se hele kart), vil det gjøre 10.000 spillobjekter i scenen. Det betyr også 10.000 unødvendig transformasjonskomponent. Jeg vet ikke ‘ om enhet kan støtte 10.000 objekt i hieararkivinduet. Jeg vet at det fryser etter par hundre.

Svar

Her er det jeg er klar over:

Alternativ 1. GameObject per brikke. Det er ikke helt forferdelig i visse tilfeller. Avhengig av dine behov kan det fungere .. godt nok.

Alternativ 2. En enkelt firhjuling eller et plan som refererer til en tekstur du lager på kjøretid. Du vil egentlig bruker du fliseatlasstrukturen til å «male» kartet ditt som en ny tekstur. Avhengig av størrelsen på kartet ditt, vil du kanskje ha flere firhjulinger / plan som hver representerer deler av kartet ditt.

Alternativ 3. Lag ditt eget nett. Dette vil mer enn sannsynlig være metoden du vil like best når du er implementert. Det vil gi deg massevis av fleksibilitet og sannsynligvis den høyeste ytelsen. Du oppretter i hovedsak en firkant per flis og stiller hvert toppunkt-UV til å tilordne flisene i fliseatlaset ditt.

For alternativ 2, jeg » foreslår at du ser denne videoserien av quill18creates: 3D TileMap tutorial-serien av quill18creates

For alternativ 3 er dette koden min, med tweaks, så det er kanskje 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

  • Svarene dine hjalp meg tilbake i dager. Nå ser jeg gjennom de gamle spørsmålene mine, og jeg ‘ har innsett at jeg ‘ aldri har sjekket dette svaret som akseptert. Beklager for en evighets sen godkjenning ^^ Takk for svaret.

Svar

Som deg (tror jeg ) hentydet til, har Unitys veikart planer for en tilemap-editor. Jeg ser frem til det, for akkurat nå er det litt forvirrende hvordan jeg skal gå frem.

I mellomtiden er den beste tilnærmingen jeg «Jeg ser er å lage kartet ditt i Tiled og deretter bruke X-UniTMX for å importere det til Unity. Åpenbart at «ikke prosessuell generasjon skjønt; jeg» forestiller meg at du vil bruke den samme teknikken som X-UniTMX bruker for å lage masken.

Svar

Du kan bare få flisene opprettet dypere i hierarkiet og lukke den mappen og ikke bry deg. Det du også kan gjøre er å skjule spillobjektene dine fra hierarkiet `myTile.hideFlags = HideFlags. HideInHierarchy «ikke sikker på hvor mye ytelse du vil oppnå.

Å vise 100×100 teksturer på skjermen er aldri en god ide å tegne teksturer er tyngre enn å tegne polygoner uansett. Hvis du trenger å zoome ut så langt, har du det bedre med større teksturer. Det samme gjelder å bli zoomet inn, du bør ikke tegne teksturene som ikke trenger å tegnes.

Det jeg vanligvis gjør (jeg er ikke en Unity-fyr) er å lage en klasse for et kart og bruke en todimensjonal matrise for å holde alle flisene dine. Denne matrisen kan bare være av ints eller en Tile-klasse med et par ints som refererer til teksturer, flisetype, objekter osv. Deretter vil man tegne 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 bruker ser ut til å være for å tegne en GUI, men kan være perfekt egnet for oppgaven. Ellers må du grave i sprite manager og finne en måte som fungerer med denne metoden.

Du kan bruke en ordbok for teksturreferanse som int 1 i fliseklassen din refererer til litt tekstur og int 2 refererer til en annen.På linjen du tegner tekstur, vil du bruke ordboken din til å gi riktig teksturobjekt. På denne måten skal det ikke skape et GameObject og dermed ikke skape alle unødvendige overhead.

Du kan gjøre det samme for stort sett alt som ikke trenger kontrollnivået til et GameObject. Men husk at på denne måten vil det tegne alle fliser på kartet ditt, det sannsynligvis ikke automatisk sletter gjenstandene slik jeg tror enhet gjør med spillobjekter. Men det er veldig enkelt å tegne det som må være på skjermen. Du kjenner skjerm / visningsstørrelse, kameraposisjon og flisestørrelse. Noen enkel matematikk skal tegne nøyaktig hva som trengs.

Likevel er enhet en 3D-motor. Den støtter bare 2D på en 3D-måte. Men du kan i utgangspunktet gjøre det samme for firhjulinger / masker med teksturer og et ortografisk kamera. Det er ganske billig å tegne de maskene som trengs.

Svar

Som noen som jobber med voxel / blokkbasert prosjekt , Jeg kan ikke unngå å tenke på å bare bruke den samme tilnærmingen, bare i 2D. Du kan bygge et rutenettlignende maske prosessuelt og tildele riktige koordinater for flisvisuelle bilder i teksturatlaset ditt til UV-kanalen. I 3D må du gjøre mye mer enn dette for å ha høy ytelse, men i 2D er det veldig sannsynlig at det er virkelig nok.

Svar

Du kan alltid bruke LeanPool . Det er en gratis eiendel i aktivaen. Det gjør objektgjenstand for deg. Deretter kan du gjøre et enkelt avlivningssystem rundt kameraets visning som gyter / de gyter fliser av spillobjekter når de går inn / ut av kameravisningen. Jeg er ikke sikker på hvor stort tilemapet ditt blir, men Unity kan håndtere ganske mange spillobjekter. LeanPool har referansescener i Unity hvor du kan gyte / de gyte tusen gjenstander med boksekollisjonskomponenter, og jeg tror muligens en gjengivelseskomponent også på hver og en, og det gjør det veldig raskt.

https://gamedevacademy.org/how-to-script-a-2d-tile-map-in-unity3d/

Her er en lenke som viser deg et eksempel på å bruke LeanPool med et tilemap.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *