I’m not sure if I am using the right terminology here, but I am trying to find a way to render some Images in a grid pattern at runtime on a UI Canvas. Essentially I want to be able to specify my own dimensions (i.e: 10x25) and then have some gameobject render within its bounds the given Texture.
I have tried getting the TileMap as a child to the UI Canvas GameObject but I have been unable to do so. I can see that I can achieve this by creating multiple “Image” gameobjects and positioning them accordingly, but this seems overly complicated for a simple task of throwing onto the screen a 2D image n times. Is there an easier way to achieve this or is this my only option?
Tilemaps are a 2D feature and don’t interact with the world of uGUI (or UI in general) at all.
uGUI uses layout components to organise rect transform objects, such as the Grid layout groups: Grid Layout Group | Unity UI | 2.0.0
1 Like
I tried using the LayoutGrid, but as it didn’t give me control over the actual positioning of the tiles other than the order i put them in, it wasn’t much use. Instead I went down the path of using individual objects which works well enough for now.
public class InvGridRenderer : MonoBehaviour
{
public GameObject templateTile;
public Vector2Int cellsize;
private class InvGridCell
{
public int X, Y;
public GameObject Obj;
public InvGridCell(int x, int y)
{
X = x;
Y = y;
}
}
private InvGridCell[,] currLayout;
// Start is called before the first frame update
void Start()
{
bool[,] example = { { false, true, false }, { true, true, true } };
SetGrid(example);
}
public bool requireUpdate;
// Update is called once per frame
void Update()
{
if (requireUpdate)
{
if (currLayout != null)
{
foreach (var cell in currLayout)
{
if (cell != null)
{
int xOffset = cell.X * cellsize.x;
int yOffset = cell.Y * cellsize.y;
var trans = cell.Obj.GetComponent<RectTransform>();
trans.anchoredPosition = new Vector3(xOffset, -yOffset);
Debug.Log("update");
}
}
}
requireUpdate = false;
}
}
private InvGridCell[,] buildLayout(bool[,] layout)
{
InvGridCell[,] retlayout = new InvGridCell[layout.GetLength(0), layout.GetLength(1)];
var colcount = layout.GetLength(1);
for (int y = 0; y < layout.GetLength(1); y++)
{
for (int x = 0; x < layout.GetLength(0); x++)
{
if (layout[x, y])
{
retlayout[x, y] = new InvGridCell(y, x);
}
}
}
return retlayout;
}
void applyLayout(InvGridCell[,] newLayout)
{
// this needs to
// 1. clear/erase the old layout
// 2. apply the new layout
if (currLayout != null)
{
foreach (var cell in currLayout)
{
if (cell != null)
{
GameObject.Destroy(cell.Obj);
}
}
currLayout = null;
}
if (newLayout != null)
{
foreach (var cell in newLayout)
{
if (cell != null)
{
cell.Obj = Instantiate(templateTile);
cell.Obj.transform.SetParent(transform, false);
cell.Obj.SetActive(true);
}
}
currLayout = newLayout;
requireUpdate = true;
}
}
void SetGrid(bool[,] layout)
{
var lo = buildLayout(layout);
applyLayout(lo);
}
}
1 Like