Eenheid procedurele TileMap-generatie zonder gameobject per tegel te maken

Ik heb op internet gezocht naar een efficiënte manier om een procedurele tilemap te maken zonder een GameObject per tegel te maken. Alle TileMap-tutorials die ik heb gevonden, maken tegels door honderden GameObjects te maken. Dus de hiërarchie in Unity breidt zich onverwachts uit.

Ik “ben er vrij zeker van dat dit niet de” juiste “manier is om het te doen. Vooral na het zien van de nieuwe Unity 2D-tools die tilemaps ondersteunen. Unity heeft het zo gemaakt, je kunt tegels maken in “één” spelobject, niet voor elke tegel.

Dus, hoe doe ik het op de juiste en effiecente manier?

Reacties

  • U ‘ heeft dit op twee SE-sites gepost. Kies er een.
  • Wat ‘ is uw specifieke zorg bij het maken van grote aantallen GameObjects? Als het ‘ slechts een rommelige hiërarchie is, zijn er eenvoudige manieren om dat op te lossen. Unity ‘ s batching zou sowieso gelijkaardige tegels in een enkele batch moeten combineren, dus het is onwaarschijnlijk dat ‘ een grote aantrekkingskracht heeft om dit op deze manier te doen. tijd besteed aan tegel-updatefuncties zijn beide ook oplosbare problemen Heb je je spel geprofileerd en een specifici? c knelpunt dat u ‘ probeert op te lossen?
  • @DMGregory Nou, als we denken aan 100 * 100 kaart op het scherm (als we aannemen dat we hebben uitgezoomd om de hele map), zal het 10.000 game-objecten in de scene maken. Het betekent ook 10.000 onnodige transformatiecomponenten. Ik weet niet ‘ zelfs niet of Unity 10.000 objecten in het hieararchievenster kan ondersteunen. Ik weet dat het vastloopt na een paar honderd.

Antwoord

Dit is waar ik me bewust van ben:

Optie 1. GameObject per tegel. In bepaalde gevallen is het niet helemaal verschrikkelijk. Afhankelijk van je behoeften zou het kunnen werken .. goed genoeg.

Optie 2. Een enkele quad of vlak die verwijst naar een texture die je tijdens runtime maakt. Je zou gebruik in wezen de structuur van je tegelatlas om je kaart als één nieuwe structuur te schilderen. Afhankelijk van de grootte van je kaart, wil je misschien meerdere quads / vlakken hebben die elk delen van je kaart vertegenwoordigen.

Optie 3. Creëer uw eigen mesh. Dit is hoogstwaarschijnlijk de methode die u het meest zult waarderen zodra deze is geïmplementeerd. Het geeft je veel flexibiliteit en waarschijnlijk de beste prestaties. Je zou in feite een quad per tegel maken en elk hoekpunt UV zo instellen dat deze wordt toegewezen aan de tegels in je tegelatlas.

Voor optie 2, I ” d stel voor om deze videoserie van quill18creates te bekijken: 3D TileMap-tutorialserie van quill18creates

Voor optie 3 is dit mijn code, met aanpassingen, dus het is misschien niet 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; } 

Reacties

  • Je antwoorden hielpen me terug in de dagen. Nu bekijk ik mijn oude vragen en ik ‘ realiseerde me dat ik ‘ dit antwoord nooit als geaccepteerd heb gecontroleerd. Sorry voor een eeuwigheid te laat goedkeuring ^^ Bedankt voor het antwoord.

Antwoord

Zoals jij (ik denk ) waarnaar wordt verwezen, heeft de roadmap van Unity plannen voor een tilemap-editor. Ik kijk er naar uit, want op dit moment is het een beetje verwarrend hoe verder te gaan.

In de tussentijd is de beste aanpak die ik “Ik zie is om je kaart in Tiled te maken en vervolgens X-UniTMX te gebruiken om deze in Unity te importeren. Dat is natuurlijk geen procedurele generatie; ik zou me voorstellen dat je dezelfde techniek zou gebruiken als X-UniTMX gebruikt om de mesh te maken.

Antwoord

Je kunt de tegels gewoon dieper in de hiërarchie laten maken en die map sluiten en je hoeft je niet druk te maken. Wat je ook kunt doen is je spelobjecten verbergen in de hiërarchie `myTile.hideFlags = HideFlags. HideInHierarchy “weet niet zeker hoeveel prestatie er zou worden behaald.

Het tonen van 100×100 texturen op het scherm is nooit een goed idee. Texturen tekenen is toch zwaarder dan polygonen tekenen. Als je zo ver moet uitzoomen, ben je beter af met grotere texturen. Hetzelfde geldt voor het inzoomen, je zou niet de texturen moeten tekenen die niet getekend hoeven te worden.

Wat ik meestal doe (ik ben geen Unity-man) is het maken van een klasse voor een kaart en een 2-dimensionale array voor al je tegels. Deze array kan simpelweg ints zijn of een Tile class met een paar ints die verwijzen naar je texturen, tegeltype, objecten, etc. Dan zou je het als volgt tekenen:

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

De tekenmethode die ik gebruik lijkt te zijn voor het tekenen van een GUI, maar is misschien perfect geschikt voor de taak. Anders moet je in de sprite-manager graven en een manier vinden dat werkt met deze methode.

Je zou een woordenboek kunnen gebruiken voor textuurreferentie zoals int 1 in je tegelklasse verwijst naar een bepaalde textuur en int 2 verwijst naar een ander.In de lijn waarin je je textuur tekent, zou je je woordenboek gebruiken om het juiste textuurobject te geven. Op deze manier zou het geen GameObject moeten creëren en dus niet alle onnodige overhead creëren.

Je kunt hetzelfde doen voor vrijwel alles dat niet het controleniveau van een GameObject nodig heeft. Let echter op, op deze manier zal het elke tegel van je kaart tekenen, het zal de objecten waarschijnlijk niet automatisch ruimen zoals ik denk dat Unity dat doet met game-objecten. Maar gewoon tekenen wat er op het scherm moet zijn, is heel eenvoudig. U kent de grootte van het scherm / viewport, de camerapositie en de tegelgrootte. Een beetje eenvoudige wiskunde zou precies moeten tekenen wat nodig is.

Toch is Unity een 3D-engine. Het ondersteunt alleen 2D op een 3D-manier. Maar je kunt in principe hetzelfde doen voor quads / meshes met texturen en een orthografische camera. Alleen al het tekenen van die meshes is best goedkoop.

Antwoord

Als iemand die werkt aan een voxel / block-based project , Kan ik niet anders dan nadenken over het gebruik van dezelfde aanpak, alleen in 2D. Je kunt procedureel een rasterachtig gaas bouwen en de juiste coördinaten van tegelvisuals in je textuuratlas toewijzen aan UV-kanaal. In 3D moet je veel meer werk doen dan dit om hoge prestaties te leveren, maar in 2D is het zeer waarschijnlijk “echt genoeg.

Answer

Je zou altijd LeanPool kunnen gebruiken . Het is een gratis aanwinst in de asset store. Het object pooling voor u. Vervolgens kun je een eenvoudig ruimingssysteem rond de cameraweergave uitvoeren dat tegel-spelobjecten spawnt / de spawnt wanneer ze de cameraweergave binnengaan / verlaten. Ik weet niet zeker hoe groot je tilemap zal zijn, maar Unity kan behoorlijk wat game-objecten aan. LeanPool heeft benchmark scènes in Unity waar je duizend objecten kunt spawnen / de spawnen met box collision-componenten en ik denk dat er mogelijk ook een rendercomponent is op elk en het doet het heel erg snel.

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

Hier is een link die u laat zien een voorbeeld van het gebruik van LeanPool met een tilemap.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *