Search Unity

Question Spawning objects on a TileMap's tiles.

Discussion in '2D' started by MaximumSpice, Oct 25, 2020.

  1. MaximumSpice

    MaximumSpice

    Joined:
    Oct 25, 2018
    Posts:
    22
    Hi guys, I've also posted on the unity 2d reddit but haven't had much luck so far so figured I'd ask here too.

    My problem is, I have a tilemap that is for tiles I've simply called BoulderSpawners, so those tiles indicate the positions of where I'd like boulders to spawn.

    I've since discovered that you need to use GridLayout.CellToWorld & Tilemap.GetCellCenterWorld
    but I am not very experienced in using lists. Still been on the list (shall I say) of things to learn.

    What currently happens is the boulder simply spawns on the tilemaps transform.position (which makes sense now that I know it) but I have no idea what my next move is to do. I will post my entire script below (at the moment is does not work because I don't know what to do to be honest).

    My understanding is, create a list of vector3 points that are stored on start of the location of each tile I paint on that tilemap, then I use that list and spawn boulders at those positions. My problem is I have no idea how to access the list, the list is vector3's and not transforms so I can't just plug them into an instantiate section.

    Anyone know what I'm doing wrong. I have tried googling and I'm not sure if I'm googling/asking the right question and I can't find videos of it on youtube so I'm stuck.

    Thanks for taking the time to read this!

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Tilemaps;
    5.  
    6. public class BoulderSpawner : MonoBehaviour
    7. {
    8.     [Header("Boulder Types")]
    9.     [SerializeField]
    10.     private GameObject boulderPrefab;
    11.     [Space(2)]
    12.  
    13.     [Header("Spawn System")]
    14.     [SerializeField]
    15.     private float spawnTimer = 0f;
    16.  
    17.     public Tilemap tileMap = null;
    18.  
    19.     public List<Vector3> availablePlaces;
    20.  
    21.     void Start()
    22.     {
    23.         tileMap = transform.parent.GetComponent<Tilemap>();
    24.         availablePlaces = new List<Vector3>();
    25.  
    26.         for (int n = tileMap.cellBounds.xMin; n < tileMap.cellBounds.xMax; n++)
    27.         {
    28.             for (int p = tileMap.cellBounds.yMin; p < tileMap.cellBounds.yMax; p++)
    29.             {
    30.                 Vector3Int localPlace = new Vector3Int(n, p, (int)tileMap.transform.position.y);
    31.                 Vector3 place = tileMap.CellToWorld(localPlace);
    32.                 if (tileMap.HasTile(localPlace))
    33.                 {
    34.                     //Tile at "place"
    35.                     availablePlaces.Add(place);
    36.                 }
    37.                 else
    38.                 {
    39.                     //No tile at "place"
    40.                 }
    41.             }
    42.         }
    43.     }
    44.  
    45.     private void Update()
    46.     {
    47.         spawnTimer += Time.deltaTime;
    48.     }
    49.  
    50.     private void FixedUpdate()
    51.     {
    52.         InvokeRepeating("SpawnBoulder", spawnTimer, 0.05f);
    53.  
    54.        
    55.     }
    56.  
    57.     private void SpawnBoulder()
    58.     {
    59.         if (spawnTimer > 2)
    60.         {
    61.             Instantiate(boulderPrefab, transform.position, Quaternion.identity); // i know this is wrong and needs to change but I don't know what to
    62.             spawnTimer = 0f;
    63.         }
    64.     }
    65. }
    66.  
    67. }
    68.  
     
  2. raarc

    raarc

    Joined:
    Jun 15, 2020
    Posts:
    535
    like this:
    Code (CSharp):
    1. for( int i = 0; i<availablePlaces.Count;i++){
    2. Instantiate(boulderPrefab, availablePlaces[i], Quaternion.identity);
    3. }
     
    blisz likes this.
  3. MaximumSpice

    MaximumSpice

    Joined:
    Oct 25, 2018
    Posts:
    22
    Is it really that simple?! Dam.

    Thank you, I shall try it tonight when I get home from work and see how it comes along.
     
  4. MaximumSpice

    MaximumSpice

    Joined:
    Oct 25, 2018
    Posts:
    22
    Just wanted to let you know, it worked beautifully! Thank you very much, now I just need to figure out how to make it find the center of the cell. One thing at a time!
     
  5. raarc

    raarc

    Joined:
    Jun 15, 2020
    Posts:
    535
    depends on your PPU

    if your cells are 1 unit size then

    Code (CSharp):
    1. Instantiate(boulderPrefab, new vector3(availablePlaces[i].x+0.5f,availablePlaces[i].y+0.5f,availablePlaces[i].z), Quaternion.identity);

    essentially add half your tile size in unity units
     
  6. MaximumSpice

    MaximumSpice

    Joined:
    Oct 25, 2018
    Posts:
    22
    I originally thought that was I had to change, since that deals with the position but I couldn't figure out what I had to do to type it out, didn't realise I could just go .x+0.5f after a square bracket. Still so much to learn.

    Instead I played around with the section before it and added this

    Code (CSharp):
    1. Vector3 place = tileMap.CellToWorld(localPlace) + new vector3(0.5f, 0.5f, 0);
    Which gave me the desired results but your method seems like its simpler and might be the more correct way of doing the change I wanted.

    I might change it to yours instead tonight when I get home, but I was so relieved to finally have the spawning system work and then get the object spawning in the center of the cell was an amazing feeling. Its been something I've put on hold for a few months now and just never came back to it until now.

    I'll post the updated script with comments tonight encase anyone in the future reads this
     
  7. MaximumSpice

    MaximumSpice

    Joined:
    Oct 25, 2018
    Posts:
    22
    Works like a charm, thanks all!


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Tilemaps;
    5.  
    6. public class BoulderSpawner : MonoBehaviour
    7. {
    8.     [Header("Boulder Types")]
    9.     [SerializeField]
    10.     private GameObject boulderPrefab;
    11.     [Space(2)]
    12.  
    13.     [Header("Spawn System")]
    14.     [SerializeField]
    15.     private float spawnTimer = 0f;
    16.     [SerializeField]
    17.     private Tilemap tileMap;
    18.     [SerializeField]
    19.     private List<Vector3> availablePlaces;
    20.  
    21.     void Start()
    22.     {
    23.         FindLocationsOfTiles();
    24.     }
    25.  
    26.     private void FindLocationsOfTiles()
    27.     {
    28.         availablePlaces = new List<Vector3>(); // create a new list of vectors by doing...
    29.  
    30.         for (int n = tileMap.cellBounds.xMin; n < tileMap.cellBounds.xMax; n++) // scan from left to right for tiles
    31.         {
    32.             for (int p = tileMap.cellBounds.yMin; p < tileMap.cellBounds.yMax; p++) // scan from bottom to top for tiles
    33.             {
    34.                 Vector3Int localPlace = new Vector3Int(n, p, (int)tileMap.transform.position.y); // if you find a tile, record its position on the tile map grid
    35.                 Vector3 place = tileMap.CellToWorld(localPlace); // convert this tile map grid coords to local space coords
    36.                 if (tileMap.HasTile(localPlace))
    37.                 {
    38.                     //Tile at "place"
    39.                     availablePlaces.Add(place);
    40.                 }
    41.                 else
    42.                 {
    43.                     //No tile at "place"
    44.                 }
    45.             }
    46.         }
    47.     }
    48.  
    49.     private void Update()
    50.     {
    51.         spawnTimer += Time.deltaTime;
    52.     }
    53.  
    54.     private void FixedUpdate()
    55.     {
    56.         InvokeRepeating("SpawnBoulder", spawnTimer, 0.05f);
    57.  
    58.        
    59.     }
    60.  
    61.     private void SpawnBoulder()
    62.     {
    63.         if (spawnTimer > 2)
    64.         {
    65.             for (int i = 0; i < availablePlaces.Count; i++)
    66.             {
    67.                 // spawn prefab at the vector's position which is at the availablePlaces location and add 0.5f units as the bottom left
    68.                 // of the CELL (square) is (0,0), the top right of the CELL (square) is (1,1) therefore, the middle is (0.5,0.5)
    69.                 Instantiate(boulderPrefab, new Vector3(availablePlaces[i].x+0.5f, availablePlaces[i].y + 0.5f, availablePlaces[i].z), Quaternion.identity);
    70.             }
    71.             spawnTimer = 0f;
    72.         }
    73.     }
    74. }
    75.  
     
    Deleted User and RafaelGaju like this.