Unitatea procedurală Generarea TileMap fără a crea gameobject per tile

Am căutat pe internet pentru a găsi o modalitate eficientă de a crea un tilemap procedural fără a crea un GameObject per tile. Toate tutorialele TileMap pe care le-am găsit creează dale creând sute de GameObjects. Astfel, ierarhia din Unity se extinde în mod neașteptat.

Sunt „destul de sigur că acest lucru nu este modul„ corect ”de a o face. Mai ales după ce am văzut noile instrumente Unity 2D care acceptă hărțile tilil. Unity a făcut acest lucru, puteți crea piese într-un „obiect” gameobject, nu pentru fiecare piesă.

Deci, cum o fac în mod corect și eficient?

Comentarii

  • ‘ ați trimis acest mesaj pe două site-uri SE. Alegeți unul.
  • Ce ‘ vă preocupă în mod specific crearea unui număr mare de GameObjects? Dacă ‘ este doar o aglomerație ierarhică, există modalități ușoare de a remedia problema. Unity ‘ loturile ar trebui să combine oricum dale similare într-un singur lot oricum, așa că este puțin probabil ca ‘ să fie o penalizare majoră a apelurilor la tragere pentru a face acest lucru. Minimizarea dalei de pe ecran și timpul petrecut în funcțiile de actualizare a plăcilor sunt ambele probleme de rezolvat. V-ați profilat jocul și ați identificat o specificație c blocaj ‘ încerci să rezolvi?
  • @DMGregory Ei bine, dacă ne gândim la o hartă de 100 * 100 în ecran (dacă presupunem că am micșorat pentru a vedea întregul hartă), va crea 10.000 de obiecte de joc în scenă. De asemenea, înseamnă 10.000 de componente de transformare inutile. Nu ‘ nici măcar nu știu dacă unitatea poate suporta 10.000 de obiecte în fereastra hieararhiei. Știu că îngheață după câteva sute.

Răspuns

Iată ceea ce știu:

Opțiunea 1. GameObject pe țiglă. Nu este complet oribil în anumite cazuri. În funcție de nevoile dvs., ar putea funcționa … destul de bine.

Opțiunea 2. Un singur quad sau plan care face referire la o textură pe care o creați în timpul rulării. folosiți în esență textura atlasului de țiglă pentru a „vopsi” harta ca o textură nouă. În funcție de dimensiunea hărții, desigur, vă recomandăm să aveți mai multe quad-uri / planuri, fiecare reprezentând porțiuni ale hărții dvs.

Opțiunea 3. Creați-vă propria rețea. Aceasta ar fi cel mai probabil metoda care vă va plăcea cel mai mult odată implementată. Vă va oferi o mulțime de flexibilitate și, probabil, cea mai înaltă performanță. În esență, veți crea un quad pentru fiecare țiglă și veți seta fiecare vârf UV pentru a le mapa cu plăcile din atlasul dvs. de plăci.

Pentru Opțiunea 2, I ” vă sugerez să vizionați această serie video de quill18creates: Seria de tutoriale 3D TileMap de quill18creates

Pentru Opțiunea 3, acesta este codul meu, cu modificări, deci este posibil să nu fie perfect:

//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; } 

Comentarii

  • Răspunsurile dvs. m-au ajutat să revin în zile. Acum, mă uit la vechile mele întrebări și ‘ mi-am dat seama că ‘ nu am verificat niciodată acest răspuns ca acceptat. Îmi pare rău pentru o aprobare întârziată cu o eternitate ^^ Vă mulțumim pentru răspuns.

Răspuns

După cum sunteți (cred ) la care se face referire, foaia de parcurs a Unity are planuri pentru un editor de hărți de tip tilemap. Aștept cu nerăbdare acest lucru, pentru că în acest moment este puțin confuz cum să procedăm.

Între timp, cea mai bună abordare I „Văd este să îți creez harta în Tiled și apoi să folosești X-UniTMX pentru a o importa în Unity. Evident că nu este o generație procedurală; aș imagina că ați folosi aceeași tehnică pe care o folosește X-UniTMX pentru a crea rețeaua.

Răspuns

Puteți face ca dale să fie create mai adânc în ierarhie și să închideți acel folder și să nu vă deranjați. Ceea ce puteți face este să ascundeți obiectele de joc din ierarhia `myTile.hideFlags = HideFlags. HideInHierarchy „nu știu cât de mult s-ar obține performanța.

Afișarea texturilor de 100×100 pe ecran nu este niciodată o idee bună. Desenarea texturilor este mai grea decât desenarea poligonelor oricum. Dacă trebuie să micșorați atât de mult, sunteți mai bine cu texturi mai mari. Același lucru este valabil și pentru mărirea, nu ar trebui să desenați texturile care nu trebuie desenate.

Ceea ce fac de obicei (nu sunt un tip Unity) este crearea unei clase pentru o hartă și utilizarea un tablou bidimensional pentru păstrarea tuturor plăcilor dvs. Acest tablou ar putea fi pur și simplu de inți sau o clasă de plăci cu câteva intimi care se referă la texturi, tip de plăci, obiecte etc. Apoi s-ar desena astfel:

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); } } 

Metoda de extragere pe care o folosesc pare să fie pentru a desena o interfață grafică, dar ar putea fi perfect potrivită pentru sarcină. În caz contrar, trebuie să căutați în managerul sprite și să găsiți o cale care funcționează cu această metodă.

Puteți utiliza un dicționar pentru referința texturii, cum ar fi int 1 în clasa dvs. de țiglă se referă la o anumită textură și int 2 se referă la altul.În linia în care îți desenezi textura, ai folosi dicționarul pentru a da obiectul texturii corect. În acest fel, nu ar trebui să creeze un GameObject și, prin urmare, să nu creeze toate cheltuielile inutile.

Puteți face același lucru pentru aproape tot ceea ce nu are nevoie de nivelul de control al unui GameObject. Ține cont, totuși, în acest fel va atrage fiecare țiglă a hărții tale, cel mai probabil nu elimină automat obiectele, așa cum cred că face unitatea cu obiectele de joc. Dar doar desenarea a ceea ce trebuie să fie pe ecran este foarte ușoară. Cunoașteți dimensiunea ecranului / ferestrei, poziția camerei și dimensiunea plăcilor. Unele matematici simple ar trebui să atragă exact ceea ce este necesar.

Totuși, unitatea este un motor 3D. Suportă doar 2D într-un mod 3D. Dar practic puteți face același lucru pentru quad-uri / ochiuri cu texturi și o cameră ortografică. Desenarea acelor ochiuri necesare este destul de ieftină.

Răspuns

Ca cineva care lucrează la un proiect bazat pe blocuri voxel / bloc , Nu mă pot abține să nu mă gândesc doar la aceeași abordare, doar în 2D. Puteți construi o rețea asemănătoare grilei procedural și să atribuiți coordonate corecte ale vizualelor de dale din atlasul texturii canalului UV. În 3D trebuie să faceți mult mai multă treabă decât aceasta pentru a avea performanțe ridicate, dar în 2D este foarte probabil că este suficient.

Răspunde

Ai putea folosi întotdeauna LeanPool . Este un activ gratuit în magazinul de active. Realizează un pooling de obiecte pentru dvs. Apoi, puteți efectua un sistem simplu de eliminare în jurul vizualizării camerelor care generează / dezvăluie obiectele jocului de plăci în timp ce intră / ies din vizualizarea camerelor. Nu sunt sigur de cât de mare va fi harta dvs. tilil, dar Unity poate gestiona destul de multe obiecte de joc. LeanPool are scene de referință în Unity în care puteți genera / de a genera o mie de obiecte cu componente de coliziune a cutiei și cred că este posibil să existe și o componentă de redare pe fiecare și o face foarte repede.

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

Iată un link care vă va arăta un exemplu de utilizare a LeanPool cu un tilemap.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *