Search code examples
c#unity-game-enginerotationisometric

How to map screen coordinates to individual Tiles in a rotated Tilemap?


I'm trying to figure out how to properly calculate a cursor's location relative to a rotated Tilemap. First, a couple pictures to illustrate the problem.

Camera rotation: 0
Tilemap rotation: 0

enter image description here Everything looks good and works great, except we're wanting the tiles to have a psuedo-3d perspective, which means rotating them along the x axis:

Camera Rotation: 0
Tilemap rotation: 60

enter image description here This gets us our perspective, however besides a narrow band of tiles near the middle, the calculation for finding the tile stops working: enter image description here

So far I've tried two different approaches that both net the same result:

var touchPosition = getScreenPosition();
var worldPosition = Camera.main.ScreenToWorldPoint(touchPosition);
worldPosition.z = 0;
var cellPosition = tilemap.WorldToCell(position);

Notably I'm having to do some z-axis manipulation to account for the camera position which I suspect could be part of my initial problem. Instead I swapped over to doing raycasts to find my intersection:

var plane = new Plane(Vector3.back, Vector3.zero);

var touchPosition = getScreenPosition();
var ray = Camera.main.ScreenPointToRay(new Vector3(touchPosition.x, touchPosition.y, 0f));
if (plane.Raycast(ray, out float hit))
{
    var point = ray.GetPoint(hit);
    var cellPosition = tilemap.WorldToCell(point);
}

That eliminated the need to adjust the z-axis, however with the Tilemap rotated I still fail to find the correct Tile. Interestingly, if I also rotate the Camera itself, everything goes back to working again without the perspective and being offset (since the camera's physical location hasn't changed).

Camera rotation: 60
Tilemap rotation: 60

enter image description here

My suspicion is that despite the raycast finding a valid hit, WorldToCell() isn't taking the transform's rotation into account when doing its conversion. I couldn't find the source for that particular function so if that's available somewhere I'll happily start there. Besides that, if someone can help point me to the math I might need to do in order to get this calculation correct, that'd be wonderful.

Many thanks!


Solution

  • Turns out the answer to this was incredibly simple: https://gamedev.stackexchange.com/a/5220 had the info I needed, specifically the sentence:

    Here is the traditional version with horizontal hexes that are effectively squished in the vertical axis to make a pseudo-isometric look.

    Instead of rotating the Tilemap 60 degrees, I simply set its Y-scale to 0.5 and voila, everything worked perfectly.