hoek rand
hoek rand

Reputation: 329

how can i dynamically generate a Gui in Unity3D via scripting?

I'm having a bit of trouble trying to dynamically generate a Gui in Unity3D. I've made a canvas with a panel as a child. I'm trying to populate this Panel with 7x4 images.

I receive a json object that has an x amount of items. Based on the amount of items I populate the panel with the amount of items received. For instance, if i receive a Json object with 28 items(7x4), I want the GUI to look like the following:

enter image description here

So like I've told, I made a canvas with a panel in the editor. In the script I made the following:

public GameObject canvas; //I use this to set the canvas after applying this script to an empty gameobject
public GameObject panel; // I do the same for the panel

In the Start method, i set the canvas as parent for the panel:

panel.transform.SetParent(canvas.transform, false);

Now that I set the panel as child to the Canvas, I want to generate 7x4 Images. Could anyone help me with this? What is the best way to generate multiple UI/Images and make it that it shows in the Panel like in the illustration?

Pretty new to Unity3D and I would like to get more familiair with scripting.

Upvotes: 2

Views: 2974

Answers (3)

hoek rand
hoek rand

Reputation: 329

Managed to fix my code. How I did it: 1. Add an empty gameobject to the editor 2. Add a canvas with a panel as a child 3. Add the following script to the empty gameobject in step 1:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class generateUI : MonoBehaviour
{
    public GameObject canvas;
    public GameObject Panel;
    public GameObject image;
    int size = 40;

    private float scaler = 0.0125f;
    void Start()
    {
        Panel.transform.SetParent(canvas.transform, false);
        GameObject[] tiles = new GameObject[size];
        Vector3 change = new Vector3(20 * scaler, 0, 0);
        for (int i = 0; i < size; i++)
        {
            tiles[i] = GameObject.Instantiate(image, transform.position, transform.rotation);

            tiles[i].transform.position += change;
            tiles[i].transform.SetParent(Panel.transform, false);
        }
    }
}

4: now add the following script to the canvas object:

using System.Collections
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI

public class DynamicGrid : MonoBehaviour
{
    public int col,row;
    void Start()
    {
        RectTransform parent = gameObject.GetComponent<RectTransform>();
        GridLayoutGroup grid = gameObject.GetComponent<GridLayoutGroup>();
        grid.cellSize = new Vector2(parent.rect.width / col, parent.rect.height / row);
    }
    void Update()
    {

    }
}

5: Set the canvas width to 1090 and height to 430

6: make a prefab from an image(100 by 100)

7: add a Grid Layout Group to the Panel

8: Set CellSize to 100 by 100 and spacing to 10 by 10

9: change the size in the generateUI script to a number you'd like to see

10: profit.

enter image description here

I now have the desired function. I followed @jour's suggestion to use a gridlayout, which I've used before while creating a mobile app with python's Kivy software.

Upvotes: 0

Hamid Yusifli
Hamid Yusifli

Reputation: 10137

Why do you set the canvas as parent for the panel from code?

So, if you need to generate all your images dynamically from code, you could do the following:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GUIBuilder : MonoBehaviour
{
    public GameObject canvas; //I use this to set the canvas after applying this script to an empty gameobject
    public GameObject panel; // I do the same for the panel

    public Vector2 ImageViewCount; // 6 * 4
    public Vector2 ImageViewSize; // 80 * 80
    public Vector2 InitialImageViewPosition; // -300 * 250
    public Vector2 ImageViewPositionOffset; // 125 * 200


    // Use this for initialization
    void Start()
    {
       GenerateImageView();
    }

    void GenerateImageView()
    {
        for (int a = 0; a < ImageViewCount.y; a++)
        {
            for (int b = 0; b < ImageViewCount.x; b++)
            {
                ImageViewBuilder(ImageViewSize, 
                new Vector2(InitialImageViewPosition.x + (ImageViewPositionOffset.x * b), 
                InitialImageViewPosition.y - (ImageViewPositionOffset.x * a)),
                panel.transform);
            }
        }
    }


    void ImageViewBuilder(Vector2 size, Vector2 position, Transform objectToSetImageView)
    {
        GameObject imageView = new GameObject("ImageView", typeof(RectTransform));
        RawImage image = imageView.AddComponent<RawImage>(); 
        //image.texture = Your Image Here
        RectTransform rectTransform = imageView.GetComponent<RectTransform>();
        rectTransform.sizeDelta = size;
        rectTransform.anchoredPosition = position;
        imageView.transform.SetParent(objectToSetImageView, false);
    }

}

Upvotes: 2

jour
jour

Reputation: 91

I think the best you could do is use Layout grid group on the panel, then set the images as children of the panel and force a rebuild layout

Grid Layout

Force rebuild layout

Upvotes: 1

Related Questions