SuperTiled2Unity icon indicating copy to clipboard operation
SuperTiled2Unity copied to clipboard

Tile placed in wrong location on Tilemap coordinates for Isometric tiles

Open imryano opened this issue 3 years ago • 4 comments

When importing an Isometric tiled project, the tilemap generated has the tiles in the incorrect position.

As I'm using grid based movement using A*, I'm tracking if a square is "walkable" by checking if a tile exists on a certain tilemap/layer, by converting the mouse location to grid coordinates.

What I have found is that the tiles seem to be moved North-East 1 square from where they are in Tiled (in other words, the origin of the tile is South-West one tile).

For example, the fence is placed here in Tiled: image Image 1

But the tilemap is sensing a tile at the position of my cursor here: image Image 2

And not on the tile with the fence on it: image Image 3

This appears to be consistent with both layers, and for every tile (not just fences). I have also tested that deleting the tile at the cursor position seen in Image 2 deletes the fence.

I'm not sure if this is a bug or just something to do with the way I've set up my Tiled project, but I'm happy to provide any information I can. Also completely understand if you don't have the time to look into it, I'm more than happy to investigate it myself, if I could be pointed in the direction of where you think this problem might be caused.

As a side note, I really appreciate the work you've done on this project, and once I'm able to figure this thing out it's going to be a dream for my workflow.

imryano avatar Nov 30 '21 00:11 imryano

Here is the code I'm using to generate that white square on the cursor position:

void Update()
{
    if (moving.Value == 1)
        return;

    Vector3Int mousePos = GetMousePosition();

    if (!mousePos.Equals(previousMousePos))
    {
        var overTile = interactiveMap.GetTile(mousePos);
        var groundTile = groundMap.GetTile(mousePos);
        if (overTile == null && groundTile != null)
        {
            interactiveMap.SetTile(previousMousePos, null); // Remove old hoverTile
            interactiveMap.SetTile(mousePos, hoverTile);
            previousMousePos = mousePos;
        }
    }
}

Vector3Int GetMousePosition()
{
    Vector2 mouseWorldPos = Camera.main.ScreenToWorldPoint(mouseInput.Mouse.Position.ReadValue<Vector2>());
    Vector3Int val = grid.WorldToCell(mouseWorldPos);
    return val;
}

imryano avatar Nov 30 '21 00:11 imryano

I also had this problem. I found that I had to offset the position by the parent of the grid's position. I don't know why it's like this, but this works for me:

        Vector3 cursor = Input.mousePosition;
        var grid = GetComponentsInChildren<Grid>();
        Vector3 pos = Camera.main.ScreenToWorldPoint(cursor);
        pos += grid[0].GetComponentInParent<Transform>().position;
        Vector3Int posInt = grid[0].WorldToCell(pos);
        posInt.z = 0;

        Ray ray = Camera.main.ScreenPointToRay(cursor);
        RaycastHit2D hit = Physics2D.GetRayIntersection(ray, Mathf.Infinity, 1 << LayerMask.NameToLayer("Terrain"));

rocifier avatar Apr 02 '22 04:04 rocifier

Any updates here? This is pretty game-breaking for me, I can't really rely on any of the grid logic because everything is just off when calling GetCellCenteredWorld() on the Tilemap or Grid. The fix by @rocifier didn't seem to work, everything is at (0,0) for me.

liukaichi avatar Jul 21 '23 01:07 liukaichi

Hi there, @liukaichi. My apologies that this is so confusing. Tiled and Unity use different coordinate systems and tile anchors and it is especially confusing when trying to navigate between the two when using isometric maps.

For the record: I don't want to discourage anyone from making the game in their heart but I've found isometric to be a giant PITA. So much so that I use staggered isometric maps instead. (But I digress)

In this quick example you can see how Tiled treats isometric coordinates ...

image

But in Unity the coordinates are backwards (and off by one) ...

image

The off-by-one is regrettable but that decision was made so that the world space origin was meaningful.

Here is the math I use the transform a screen position from Unity coordinates to Tiled coordinates.

    public static Vector2Int GetIsometricTiledCellFromScreenPosition(Grid grid, Camera camera, Vector3 screenPosition)
    {
        var worldPoint = camera.ScreenToWorldPoint(screenPosition);

        Vector3Int unityCellPosition = grid.WorldToCell(worldPoint);
        Vector2Int tiledCellPosition = new Vector2Int(-unityCellPosition.y - 1, -unityCellPosition.x - 1);

        return tiledCellPosition;
    }

With this I'm able to get the same logical cell coordinates I get when I move my mouse around in Tiled. I hope that helps.

Seanba avatar Jul 24 '23 02:07 Seanba