Génération de TileMap procédurale Unity sans créer un gameobject par tuile

Jai cherché sur Internet pour trouver un moyen efficace de créer un tilemap procédural sans créer un GameObject par tuile. Tous les didacticiels TileMap que jai trouvés créent des tuiles en créant des centaines de GameObjects. Ainsi, la hiérarchie dans Unity se développe de manière inattendue.

Je suis presque sûr que ce nest pas la « bonne » façon de le faire. Surtout après avoir vu les nouveaux outils Unity 2D qui prennent en charge les plans de tuiles. Unity la fait, vous pouvez créer des tuiles dans « un » objet de jeu, pas pour chaque tuile.

Alors, comment puis-je le faire correctement et efficacement?

Commentaires

  • Vous ‘ avez posté ceci sur deux sites SE. Choisissez-en un.
  • Quoi ‘ est-ce que vous êtes particulièrement préoccupé par la création d’un grand nombre de GameObjects? Le traitement par lots de>

devrait de toute façon combiner des tuiles similaires en un seul lot, donc il est peu probable que ‘ soit une pénalité majeure pour les appels de tirage au sort de cette manière. Minimiser les tuiles hors écran et le temps passé dans les fonctions de mise à jour des tuiles sont également des problèmes résolus. Avez-vous profilé votre jeu et identifié une spécifi c goulot détranglement que vous ‘ essayez de résoudre?

  • @DMGregory Eh bien, si nous pensons à une carte 100 * 100 à lécran (si nous supposons que nous avons fait un zoom arrière pour voir tout map), cela créera 10.000 objets de jeu dans la scène. Cela signifie également 10 000 composants de transformation inutiles. Je ne ‘ t même pas savoir si l’unité peut prendre en charge 10 000 objets dans la fenêtre Hieararchy. Je sais quil se fige après quelques centaines.
  • Réponse

    Voici ce que je sais:

    Option 1. GameObject par tuile. Ce nest pas complètement horrible dans certains cas. Selon vos besoins, cela pourrait fonctionner … assez bien.

    Option 2. Un seul quad ou plan référençant une texture que vous créez au moment de lexécution. utilisez essentiellement la texture de votre atlas de tuiles pour « peindre » votre carte comme une nouvelle texture. En fonction de la taille de votre carte, bien sûr, vous voudrez peut-être avoir plusieurs quads / plans représentant chacun des parties de votre carte.

    Option 3. Créez votre propre maillage. Ce sera probablement la méthode que vous aimerez le plus une fois implémentée. Cela « vous donnera des tonnes de flexibilité et probablement les plus hautes performances. Vous créeriez essentiellement un quad par tuile et définiriez chaque UV de sommet pour correspondre aux tuiles de votre atlas de tuiles.

    Pour loption 2, je » Je suggère de regarder cette série de vidéos de quill18creates: Série de didacticiels 3D TileMap par quill18creates

    Pour loption 3, voici mon code, avec des ajustements, donc ce nest peut-être pas parfait:

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

    Commentaires

    • Vos réponses mont aidé à revenir dans le jours. Maintenant, je regarde mes anciennes questions, et je ‘ jai réalisé que je ‘ nai jamais vérifié cette réponse comme acceptée. Désolé pour une approbation tardive dune éternité ^^ Merci pour la réponse.

    Réponse

    Comme vous (je pense ) a fait allusion, la feuille de route de Unity a des plans pour un éditeur de tilemap. Jattends avec impatience, car pour le moment cest un peu déroutant comment procéder.

    En attendant, la meilleure approche je «Je vois est de créer votre carte dans Tiled, puis dutiliser X-UniTMX pour limporter dans Unity. De toute évidence, ce nest pas une génération procédurale; jimagine que vous utiliseriez la même technique que X-UniTMX utilise pour créer le maillage.

    Réponse

    Vous pouvez simplement créer les tuiles plus profondément dans la hiérarchie et fermer ce dossier sans être dérangé. Ce que vous pouvez aussi faire est de cacher vos objets de jeu de la hiérarchie `myTile.hideFlags = HideFlags. HideInHierarchy « nest pas sûr des performances qui seraient gagnées.

    Afficher des textures 100×100 à lécran nest jamais une bonne idée de dessiner des textures est plus lourd que de dessiner des polygones de toute façon. Si vous avez besoin de zoomer aussi loin, vous êtes mieux avec des textures plus grandes. Il en va de même pour un zoom avant, vous ne devriez pas dessiner les textures qui nont pas besoin dêtre dessinées.

    Ce que je fais habituellement (je ne suis pas un gars dUnity), cest créer une classe pour une carte et lutiliser un tableau à 2 dimensions pour contenir toutes vos tuiles. Ce tableau pourrait être simplement des entiers ou une classe Tile avec quelques entiers qui font référence à vos textures, type de tuile, objets, etc. Ensuite, on le dessinerait comme suit:

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

    La méthode de dessin que jutilise semble être pour dessiner une interface graphique mais pourrait parfaitement convenir à la tâche. Sinon, vous devez fouiller dans le gestionnaire de sprites et trouver un moyen qui fonctionne avec cette méthode.

    Vous pouvez utiliser un dictionnaire pour la référence de texture comme int 1 dans votre classe de tuiles fait référence à une texture et int 2 fait référence à un autre.Dans la ligne que vous dessinez votre texture, vous utiliseriez votre dictionnaire pour donner le bon objet de texture. De cette façon, il ne devrait pas créer un GameObject et ainsi ne pas créer tous les frais généraux inutiles.

    Vous pouvez faire de même pour à peu près tout ce qui na pas besoin du niveau de contrôle dun GameObject. Attention cependant, de cette façon, il dessinera chaque tuile de votre carte, il ne supprimera probablement pas automatiquement les objets comme je pense que lunité le fait avec les objets du jeu. Mais dessiner simplement ce qui doit être à lécran est très facile. Vous connaissez la taille de lécran / de la fenêtre, la position de la caméra et la taille de la vignette. Quelques calculs simples devraient dessiner exactement ce qui est nécessaire.

    Pourtant, unity est un moteur 3D. Il prend simplement en charge la 2D de manière 3D. Mais vous pouvez en gros faire la même chose pour les quads / maillages avec des textures et une caméra orthographique. Le simple fait de dessiner les maillages nécessaires est assez bon marché.

    Réponse

    En tant que personne travaillant sur un projet basé sur voxel / bloc , Je ne peux pas mempêcher de penser à utiliser la même approche, uniquement en 2D. Vous pouvez créer un maillage en forme de grille de manière procédurale et attribuer les bonnes coordonnées des visuels de mosaïque dans votre atlas de textures au canal UV. En 3D, vous devez faire beaucoup plus de travail que celui-ci pour avoir des performances élevées, mais en 2D, cest très probablement suffisant.

    Réponse

    Vous pouvez toujours utiliser LeanPool . Cest un actif gratuit sur le magasin dactifs. Il fait le pool dobjets pour vous. Ensuite, vous pouvez faire un système de sélection simple autour de la vue des caméras qui génère / fait apparaître des objets de jeu de tuiles lorsquils entrent / sortent de la vue des caméras. Je ne suis pas sûr de la taille de votre tilemap, mais Unity peut gérer pas mal dobjets de jeu. LeanPool a des scènes de référence dans Unity où vous pouvez engendrer / générer un millier dobjets avec des composants de collision de boîte et je pense peut-être aussi un composant de rendu sur chacun deux et il le fait très très rapidement.

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

    Voici un lien qui vous montrera un exemple dutilisation de LeanPool avec un tilemap.

    Laisser un commentaire

    Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *