1
\$\begingroup\$

I am trying to get the sprite of a tile in unity from where a raycast hits. Right now it only works in some cases, and always in positive x.

This is my current code.

Vector3Int LocalPos = new Vector3Int((int)hit.point.x, (int)hit.point.y,0);

Sprite spr = tilemap.GetSprite(LocalPos);

From what I can tell it gets the correct sprite.

Edit: I removed pointless code

\$\endgroup\$
  • \$\begingroup\$ Your question body seems to be at odds with the title. The title asks for how to get a tile from a tilemap, but the code seems to try to find the color of a pixel and you write that "you get the correct sprite", so getting the tile seems to be a problem you have already solved. \$\endgroup\$ – Philipp Sep 15 '19 at 19:11
  • \$\begingroup\$ @Philipp The problem is it only gets tiles in certain cases. \$\endgroup\$ – Tiki720 Sep 15 '19 at 19:15
  • \$\begingroup\$ I think that you cannot obtain the single tile, but only the whole TileMap. \$\endgroup\$ – FSic Sep 17 '19 at 12:53
1
\$\begingroup\$

I guess you should read the manual, how Unity Tilemap is structured. If you create a Tilemap in Unity Editor, first you have a Grid and then a Tilemap under it. If you move Grid, Tilemap will move along it. This same thing is true for getting tiles in code. Tiles are stored in GridLayout space not in world space. So if you happen to start "drawing" you tiles from Scene world position 0,0,0 that doesn't mean Grid origin couldn't be in other location (like -2,-2,0 for example).

So one solution is to first convert screen mouse position to ray, then Raycast with this Ray against a plane matching Tilemap plane, then convert the world hit point to Grid space cell position and try to get a Tile.

It has been quite a while since I touched Tilemap and I'm no professional coder by any means, but this is one way to get your tiles under mouse cursor. I guess there might be more cleaner and shorter ways to do this...

if (Input.GetMouseButtonDown(0))
{
    // mouse position in screen space
    var mpos = Input.mousePosition;

    // Create a ray from camera to world
    var ray = Camera.main.ScreenPointToRay(mpos);

    // Create a Plane object to raycast against
    // Assume Tilemap resides on plane z 0
    var plane = new Plane(Vector3.back, Vector3.zero);

    // Do a Plane Raycast with your screen to world ray
    float hitDist;
    plane.Raycast(ray, out hitDist);

    // If you aimed towards this infinite Plane, it hit
    var point = ray.GetPoint(hitDist);
    Debug.Log("Point: " + point);

    // Convert hitpoint to Tilemap / GridLayout space
    // Cell position is an integer positions in GridLayout
    var tpos = tilemap.WorldToCell(point);

    // Try to get a tile from cell position
    var tile = tilemap.GetTile(tpos);

    if (tile != null)
    {
        // A tile exists in this cell
        Debug.Log("Tile sprite: " + tilemap.GetSprite(tpos));
    }
}

See also:

https://docs.unity3d.com/ScriptReference/Tilemaps.Tilemap.html

https://docs.unity3d.com/ScriptReference/GridLayout.html

https://docs.unity3d.com/ScriptReference/Plane.html

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.