- Home /
Using Matrix4x4.TRS to rotate Tilemap
Hi, I'm working on a 2D game and trying to rotate a section of my Tilemap 90 degrees on the Z-axis via using the Tilemap.SetTransformMatrix function. From building on the sample code and Matrix4x4.TRS from the scripting API I can get the selected area of the Tilemap to rotate, but the tiles are rotating individually in place instead of as a group as I wanted.
Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 90f), Vector3.one);
//code gets list of vector3int locations for all the square region of tiles to get rotated
//then foreach location found:
tilemap.RemoveTileFlags(location, TileFlags.LockTransform); //remove lock so tiles can be rotated
tilemap.SetTransformMatrix(location, matrix); //apply matrix
I've found lots of Tilemap tutorials, but none have discussed group rotation of tiles, just singular ones. I would be very happy if someone can tell me what I am doing wrong.
Update: I wrote this horrible proof of concept code while testing which rotates the 3x3 center section of my tilemap 90 degrees clockwise as a group, without affecting the rotation value of the tilemap itself which is what I wanted:
There has to be an easier/much more efficient way to do this?
Matrix4x4 matrix = Matrix4x4.TRS(new Vector3Int(2, 0, 0), Quaternion.Euler(0f, 0f, -degreesRotated), Vector3.one);
tmap.SetTransformMatrix(new Vector3Int(-1, 1, 0), matrix);
matrix = Matrix4x4.TRS(new Vector3Int(0, 2, 0), Quaternion.Euler(0f, 0f, -degreesRotated), Vector3.one);
tmap.SetTransformMatrix(new Vector3Int(-1, -1, 0), matrix);
matrix = Matrix4x4.TRS(new Vector3Int(-2, 0, 0), Quaternion.Euler(0f, 0f, -degreesRotated), Vector3.one);
tmap.SetTransformMatrix(new Vector3Int(1, -1, 0), matrix);
matrix = Matrix4x4.TRS(new Vector3Int(0, -2, 0), Quaternion.Euler(0f, 0f, -degreesRotated), Vector3.one);
tmap.SetTransformMatrix(new Vector3Int(1, 1, 0), matrix);
matrix = Matrix4x4.TRS(new Vector3Int(-1, 0, 0), Quaternion.Euler(0f, 0f, -degreesRotated), Vector3.one);
tmap.SetTransformMatrix(new Vector3Int(2, 1, 0), matrix);
matrix = Matrix4x4.TRS(new Vector3Int(1, -1, 0), Quaternion.Euler(0f, 0f, -degreesRotated), Vector3.one);
tmap.SetTransformMatrix(new Vector3Int(0, 1, 0), matrix);
matrix = Matrix4x4.TRS(new Vector3Int(1, 1, 0), Quaternion.Euler(0f, 0f, -degreesRotated), Vector3.one);
tmap.SetTransformMatrix(new Vector3Int(-1, 0, 0), matrix);
matrix = Matrix4x4.TRS(new Vector3Int(-1, 1, 0), Quaternion.Euler(0f, 0f, -degreesRotated), Vector3.one);
tmap.SetTransformMatrix(new Vector3Int(0, -1, 0), matrix);
matrix = Matrix4x4.TRS(new Vector3Int(-1, -1, 0), Quaternion.Euler(0f, 0f, -degreesRotated), Vector3.one);
tmap.SetTransformMatrix(new Vector3Int(1, 0, 0), matrix);
try tilemapTransform.rotation = Quaternion.Euler(0f, 0f, 90f);
instead
Hi thanks for the reply, this was the method I was originally considering, however it rotates the entire tilemap and not just the selected area, which in turn affects all the code for player movement.
Answer by Namey5 · Mar 07, 2021 at 11:34 PM
I'm not familiar with tilemaps specifically, but if you can rotate and reposition the tiles then you should have everything you need. The basic idea would be to set the rotation of the tiles to what you desire, then rotate their positions around the centre of the transformation by the rotation;
Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 90f), Vector3.one);
//Assuming this rotates the tiles correctly
tilemap.SetTransformMatrix (location, matrix);
//Then, rotate each tile's position using the transform matrix;
foreach (tile in tilemap)
tile.position = matrix.MultiplyPoint (tile.position);
Appreciate the reply, from my experience it's impossible to set the position of the tiles directly using something like tile.position = matrix.MultiplyPoint (tile.position);
which is not recognized by Unity. I've only been able to manage this by modifying the matrix which is being passed to tilemap.SetTransformMatrix(location, matrix)
Eg I modify my code to Matrix4x4 matrix = Matrix4x4.TRS(Vector3.up, Quaternion.Euler(0f, 0f, 90f), Vector3.one);
It will rotate all tiles 90 degrees and also increase their Y position value by 1 for each tile