0
\$\begingroup\$

I am learning Unity and for now trying to rotate a tilemap using (x, y) --> (-y, x). I have created a Grid and tilemap in it Scene view As you can see my tiles are in cells of izometric tilemap. I am expected that each diamond is represent 'cell' and have integer coordinates (x, y) like (0, 1), see the picture below Expected result But I can see that it is not work so

Actual coordinates

The problem is that if I try to use standart tilemap function like GetTile it is return wrong coordinates of the tile bcs it is use Vector3Int datatype, but in reality it seems obvious that coordinates is float. This problem leads to mistakes in rotation matrix.

It seems that when I chooce a cell layout property of tilemap to "Isometric" it is not change coordinate system to isometric projection.

Am I working correctly with isometric tilemap system? Or is this sort of unity's bug?

Upd: here is the source code of the script that I wrote Here how I instantiate tilemap

public class BaseTilemapInit : MonoBehaviour

    {
        [SerializeField]
        private Tilemap _tilemap;
        [SerializeField]
        private Tile _tilePrefab;
        [SerializeField]
        private int _width;
        [SerializeField]
        private int _height;
        [SerializeField] private float _tileWidth = 1.0f;
        [SerializeField] private float _tileHeight = 0.5f;
        
        // Start is called before the first frame update
        void Start()
        {
            Instantiate();
            _tilemap.CompressBounds();
        }
    
        public void Instantiate(){
            int offsetX = _width/2;
            int offsetY = _height/2;
    
            for (int x = 0; x < _width; x++){
                for (int y = 0; y < _height; y++){
                    _tilemap.SetTile (new Vector3Int (x, y, 0), _tilePrefab);
                }
            }
        }
    
        public int GetWidth()
        {
            return _width;
        }
    
        public int GetHeight()
        {
            return _height;
        }
    
        public float GetTileWidth()
        {
            return _tileWidth;
        }
    
        public float GetTileHeitht()
        {
            return _tileHeight;
        }
        public Tilemap GetTilemap()
        {
            return _tilemap;
        }
    }

And here is a camera controller which is responsible for positioning and rotating (okay not camera but anyway)

public class CameraController : MonoBehaviour
{
    //[SerializeField]
    //private Tilemap _tilemap;
    [SerializeField] private BaseTilemapInit _tiles;
    [SerializeField] private Transform _cam;
    private Tilemap _tilemap;
    private CameraControls cameraActions;
    private InputAction rotation;
    private Transform cameraTransform;

    void Start()
    {
        SetStartCameraPosition();
    }

    private void SetStartCameraPosition()
    {
        float width = _tiles.GetWidth();
        float height = _tiles.GetHeight();

        Vector2 gridCenter = new Vector2(width / 2, height / 2);
        Vector2 isoCenter = GridToIsometric(gridCenter);
        _cam.transform.position = new Vector3(isoCenter.x, isoCenter.y, _cam.transform.position.z);
    }

    private Vector2 GridToIsometric(Vector2 gridPos) {
        
        float tileWidth = _tiles.GetTileWidth(); 
        float tileHeight = _tiles.GetTileHeitht(); 

        float isoX = (gridPos.x - gridPos.y) * tileWidth * 0.5f;
        float isoY = (gridPos.x + gridPos.y) * tileHeight * 0.5f;
        return new Vector2(isoX, isoY);
    }

    private void Awake()
    {
        cameraActions = new CameraControls();
        cameraTransform = this.GetComponentInChildren<Camera>().transform;
    }

    private void OnEnable()
    {
        cameraActions.Camera.RotateClockwise.performed += RotateClockwise;
        cameraActions.Camera.Enable();
    }

    private void OnDisable()
    {
        cameraActions.Camera.RotateClockwise.performed -= RotateClockwise;
        cameraActions.Camera.Disable();
    }

    private void RotateClockwise(InputAction.CallbackContext context)
    {
        _tilemap = _tiles.GetTilemap();
        Debug.Log("Pressed E");
        Rotate (_tilemap);
    }

    void Rotate(Tilemap tilemap)
    {
        BoundsInt bounds = tilemap.cellBounds;

        for (int x = bounds.xMin; x < bounds.xMax; x++){
            for (int y = bounds.yMin; y < bounds.yMax; y++){
                Vector3Int position = new Vector3Int (x, y, 0);
                TileBase tile = tilemap.GetTile(position);
                if (tile != null){
                    Debug.Log ($"Tile {tile.name} at {position}");


                    Vector3Int newposition = Rotatation(position);
                    //Vector3Int newposition = IsoToCart(position);
                    tilemap.SetTile(position, null);
                    tilemap.SetTile(newposition, tile);  
                }
                else{
                    Debug.Log($"No tile at {position}");
                }
            }
        }
        //_tiles.GetTilemap().CompressBounds();
    }

    private Vector3Int Rotatation(Vector3Int pos)
    {
        int x = pos.x;
        int y = pos.y;
        int z = pos.z;

        int newX = (-1) * y;
        int newY = (1) * x;

        Vector3Int newPos = new Vector3Int(newX, newY, pos.z);

        return newPos;
    } 
    private Vector3Int IsoToCart(Vector3Int pos)
    {
        int x = pos.x;
        int y = pos.y;
        int z = pos.z;

        int newX = (x - y)/2;
        int newY = (x + y)/2;

        Vector3Int newPos = new Vector3Int(newX, newY, z);

        return newPos;
    }
    void OnDrawGizmos()
    {
        Tilemap tilemap = _tiles.GetTilemap();
        if (tilemap != null)
        {
            Gizmos.color = Color.green;
            BoundsInt bounds = tilemap.cellBounds;
            Vector3Int min = bounds.min;
            Vector3Int max = bounds.max;

            Vector3[] corners = new Vector3[4];
            corners[0] = tilemap.CellToWorld(new Vector3Int(min.x, min.y, min.z));
            corners[1] = tilemap.CellToWorld(new Vector3Int(max.x, min.y, min.z));
            corners[2] = tilemap.CellToWorld(new Vector3Int(max.x, max.y, min.z));
            corners[3] = tilemap.CellToWorld(new Vector3Int(min.x, max.y, min.z));

            Gizmos.DrawLine(corners[0], corners[1]);
            Gizmos.DrawLine(corners[1], corners[2]);
            Gizmos.DrawLine(corners[2], corners[3]);
            Gizmos.DrawLine(corners[3], corners[0]);
        }
    }
}
\$\endgroup\$
7
  • \$\begingroup\$ Did you want to use GetCellCenterWorld to convert the integer tile grid coordinates into the floating point coordinates where the tile is positioned in world space? \$\endgroup\$ Commented Feb 4, 2024 at 12:48
  • \$\begingroup\$ Actually I am trying to rotate grid using (x, y) => (y, -x). But it is work bad in isometric projection \$\endgroup\$ Commented Feb 4, 2024 at 13:27
  • \$\begingroup\$ Perhaps you should show the code you're using. \$\endgroup\$ Commented Feb 4, 2024 at 13:56
  • \$\begingroup\$ I updated my post an provided a source code \$\endgroup\$ Commented Feb 4, 2024 at 18:50
  • 1
    \$\begingroup\$ Want to edit your question to clarify what the real problem was, then post your solution as an Answer below? \$\endgroup\$ Commented Feb 4, 2024 at 19:39

1 Answer 1

0
\$\begingroup\$

Okay I finally understood how it works. The key point here is that I try simply to rewrite tiles doing so:

for(...){
   ... 
   tilemap.SetTile(position, null);
   tilemap.SetTile(newposition, tile); 
   ...
}

So sometimes from diamond-shaped tilemap I got tile at completely wrong positions.

The solution that helps me is: Store new position somehow (I had chosen a Dictionary)

Dictionary<Vector3Int, TileBase> tilesPositions = new Dictionary<Vector3Int, TileBase>();
   for(...){
   ...
   Vector3Int newposition = Rotatation(position);//here Rotation do (x, y) -> (-y, x)
   tilesPositions[newposition] = tile; 
  ...
  }

Then clear all tiles and set it from Dictionary

tilemap.ClearAllTiles();
foreach (var item in tilesPositions)
{
    tilemap.SetTile(item.Key, item.Value);
}
tilemap.CompressBounds();
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.