WokerHead
WokerHead

Reputation: 967

Unity3D: GridLayout keeps adding 1 element under the last element when count is 1

Unity3D 2018.2

So I have a canvas that gets deactivated and reactivated at users choice. I have a List filled with transforms in which I populated the Grid with. I also have another List to hold all the images that will be used to populate the Grid with, since what the grid is being populated with are buttons containing the transform. For example if I click the button and run Debug.Log("transform.name"), I should see all my different transforms.

Problem 1: Every time this canvas gets enabled or disabled, the grid keeps adding 1 element under the initial one, and after being enabled/disabled again, another element is instantiated under that one.

+

Problem 2: Also none of these instantiated buttons get called. Maybe the problem here is due to the 1st problem?

Here is the code I have for inside the button I have

public class SatelliteButton : MonoBehaviour {

[SerializeField]
private Image myIcon;

 public void SetIcon(Sprite mySprite)
 {
     myIcon.sprite = mySprite;
 }

 public void OnMouseEnter()
 {
     Debug.Log(transform.name);
 }
}

Here is the code for populating the grid

public class SatelliteGridControl : MonoBehaviour {

private List<Transform> satelliteListFromPlanet;

[SerializeField]
private GameObject buttonTemplate;
[SerializeField]
private GridLayoutGroup gridGroup;
[SerializeField]
private List<Sprite> iconSprites;

// Use this for initialization
void OnEnable()
{
    getSatellitesInPlanet();
    genInventory();
}

//  Get Satellites
private void getSatellitesInPlanet()
{
    satelliteListFromPlanet = new List<Transform>();

    //  Get current planet
    Transform currentPlanet = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<HandleCamera>().targetToLookAt;

    //  Check inside for satellites
    foreach (Transform satellite in currentPlanet)
    {
        //  Check transform for tag
        if (satellite.CompareTag("Satellite"))
        {
            //  Add each transform from planet to array
            satelliteListFromPlanet.Add(satellite);
        }
    }
}

//  Handle Grid
private void genInventory()
{
    if (satelliteListFromPlanet.Count < 6)
    {
        gridGroup.constraintCount = satelliteListFromPlanet.Count;
    }
    else
    {
        gridGroup.constraintCount = 5;
    }

    foreach (Transform sat in satelliteListFromPlanet)
    {
        GameObject newButton = Instantiate(buttonTemplate) as GameObject;
        newButton.SetActive(true);

        newButton.GetComponent<SatelliteButton>().SetIcon(iconSprites[Random.Range(0, iconSprites.Count)]);
        newButton.transform.SetParent(buttonTemplate.transform.parent, false);
    }
 }
}

I appreciate the help! Learning about grid layouts with List<>!

Upvotes: 0

Views: 291

Answers (2)

derHugo
derHugo

Reputation: 90724

In genInventory() you Instantiate a new button for every Transform in satelliteListFromPlanet. Since only 1 is added it seems that your list only contains 1 element.

But you never destroy/remove this Instantiated GameObjects, so the next time you re-enable the object, OnEnable will be called again and new prefabs are Instantiated.

Solution:

Make sure to store the Instantiated objects somewhere e.g.

private List<GameObject> instances = new List<GameObject>();

//....

foreach (Transform sat in satelliteListFromPlanet)
{
    GameObject newButton = Instantiate(buttonTemplate) as GameObject;
    newButton.SetActive(true);

    newButton.GetComponent<SatelliteButton>().SetIcon(iconSprites[Random.Range(0, iconSprites.Count)]);
    newButton.transform.SetParent(buttonTemplate.transform.parent, false);

    instances.Add(newButton);
}

And than you can destroy them when you disable the object:

private void OnDisable()
{
    foreach(var instance in instances)
    {
        Destroy(instance);
    }
}

Upvotes: 1

Steven Coull
Steven Coull

Reputation: 478

Problem 1: Every time this canvas gets enabled or disabled, the grid keeps adding 1 element under the initial one, and after being enabled/disabled again, another element is instantiated under that one.

Right now you're calling getSatellitesInPlanet() on SatelliteGridControl's OnEnabled() method. This method is called every time the object is set to active. If you just want to call your method once, use Start.

Problem 2: Also none of these instantiated buttons get called. Maybe the problem here is due to the 1st problem?

I don't think the problems are related. Can you confirm that your buttonTemplate prefab has an Image element and its RaycastTarget is enabled?

Just one tip, I would set the type of buttonTemplate to SatelliteButton, not GameObject. That way you can instantiate it as type SatelliteButton and avoid the need to call:

newButton.GetComponent<SatelliteButton>()

Upvotes: 1

Related Questions