Drawing a Guid/Tilemap in a UI Canvas

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