Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set tile in tilemap dynamically?

Tags:

unity3d

I'm using Isometric Tilemap to make my game map.
I'm using unity 2018 3.5f version.

But every guide said that just use palette, but my game tilemap is a little dynamic. So I can add, change and delete tiles in tilemap at runtime (dynamically). And I must read the tile data from map xml files. So i can add tiles by programmatically. In reference there is a 'setTile()' method. But there is no proper example about use this. Should I create tile game object first and drag it to prefabs folder for make it tile prefab. And I must use like this?

setTile(position , TilePrefab.Instantiate());

May I get some example for how to use setTile to add tiles programatically. And I'm a newbie of unity so if you mind please give more tips or advice about tilemap (just anything).

like image 341
HelloWorld Avatar asked Feb 26 '19 15:02

HelloWorld


2 Answers

This does not seem like a "newbie" question at all. It seems fairly clear that you just want to lay down tiles programmatically rather than via the editor.

I ran in to the same question because I wanted to populate my tiles based on a terrain generator. It's surprising to me that the documentation is so lacking in this regard, and every tutorial out there seems to assume you are hand-authoring your tile layouts.

Here's what worked for me:

This first snippet does not answer your question, but here's my test code to lay down alternating tiles in a checkerboard pattern (I just have two tiles, "water" and "land")

for (int x = 0; x < 10; x++)
{
    for (int y = 0; y < 10; y++)
    {
        Vector3Int p = new Vector3Int(x,y,0);
        bool odd = (x + y) % 2 == 1;
        Tile tile = odd ? water : land;
        tilemap.SetTile(p, tile);
    }
}

In order to get an instance of a Tile, I found that two different methods worked:

Method 1: Hook up Tiles to properties using Editor

In the MonoBehaviour class where you are writing the code to programmatically generate the tile layout, expose some public properties:

public Tile water;
public Tile land;

Then in the Unity Inspector, these fields will appear. If you press the little bullseye next to these properties it will open up a "Select Tile" window where you should be able to see any tiles that you have previously added to the Tile Palette

Method 2: Programmatically Create Tile from Texture in Resources folder

If you have a lot of different tile types, manually hooking up properties as described above may become tedious and annoying.

Also if you have some intelligent naming scheme for your tiles which you want to take advantage of in code, it will probably make more sense to use this second method. (e.g. maybe you have four variants of water and four of land that are called water_01, water_02, water_03, water_04, land_01, etc., then you could easily write some code to load all textures "water_"+n for n from 1 to numVariants).

Here's what worked for me to load and create a Tile from a 128x128 texture saved as Assets/Resources/Textures/water.png:

Tile water = new Tile();
Texture2D texture = Resources.Load<Texture2D>("Textures/water") as Texture2D;
water.sprite = Sprite.Create(texture,
    new Rect(0, 0, 128, 128), // section of texture to use
    new Vector2(0.5f, 0.5f), // pivot in centre
    128, // pixels per unity tile grid unit
    1,
    SpriteMeshType.Tight,
    Vector4.zero
);
like image 182
uglycoyote Avatar answered Sep 26 '22 21:09

uglycoyote


I stumbled across this question a year later and had to make tweaks to uglycoyote's answer to get it to work with RuleTiles, so I thought I would post the change I had to make just in case someone else finds this answer.

The good news is that you can also implement RuleTiles this way! Instead of creating Tile properties, I had to create TileBase properties instead, like so:

public TileBase water;
public TileBase grass;

Also, in this same class, create a Tilemap property and make it public like so:

public Tilemap tileMap;

Now, go into the inspector and drag your tiles, whether they be RuleTiles or normal tiles, into the exposed tile properties, and drag the tilemap from the hierarchy view into the exposed tileMap property. This gives you a reference to that tileMap object from within this class.

From here, it's as simple as creating a for loop to populate the tilemap:

for(int x = 0; x < 10; x++) {
    for(int y = 0; y < 10; y++) {
        tileMap.SetTile(new Vector3Int(x, y, 0), grass);
    }
}

For instance, the above will create a 10x10 map of just grass tiles, but you can do whatever you want inside the nested for loops.

like image 30
Stewcooker Avatar answered Sep 22 '22 21:09

Stewcooker