Unity3D: GridLayout 在计数为 1 时一直在最后一个元素下添加 1 个元素

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

Unity3D 2018.2

所以我有一个 canvas 可以根据用户的选择停用和重新激活。我有一个充满转换的列表,我在其中填充了网格。我还有另一个列表来保存将用于填充网格的所有图像,因为填充网格的是包含转换的按钮。例如,如果我单击按钮和 运行 Debug.Log("transform.name"),我应该会看到所有不同的转换。

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?

这是我在按钮中的代码

public class SatelliteButton : MonoBehaviour {

[SerializeField]
private Image myIcon;

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

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

这是填充网格的代码

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);
    }
 }
}

感谢您的帮助!使用 List<>!

了解网格布局

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.

现在您正在 SatelliteGridControl 的 OnEnabled() 方法上调用 getSatellitesInPlanet()。这个方法叫做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?

我不认为这些问题是相关的。您能否确认您的 buttonTemplate 预制件具有 Image 元素并且其 RaycastTarget 已启用?

一个提示,我会将 buttonTemplate 的类型设置为 SatelliteButton,而不是 GameObject。这样您就可以将其实例化为 SatelliteButton 类型并避免调用:

newButton.GetComponent<SatelliteButton>()

genInventory() 中,您为 satelliteListFromPlanet 中的每个 Transform 实例化一个新按钮。由于只添加了 1 个,因此您的列表似乎只包含 1 个元素。

但是你从来没有destroy/remove这个实例化的游戏对象,所以下次你重新启用这个对象时,OnEnable将再次被调用并且新的预制件被实例化。

解决方案:

确保将实例化对象存储在某处,例如

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);
}

而且你可以在禁用对象时销毁它们:

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