首页 > 解决方案 > 在遍历数组后尝试从列表中获取随机元素时,ArgumentOutOfRangeException 错误 Unity3D C#

问题描述

问题: 在遍历数组后尝试从列表中获取随机元素时出现 ArgumentOutOfRangeException 错误。

目标: 我试图通过查找标签来激活父游戏对象内的随机子游戏对象。父级中有多个子游戏对象。如果该游戏对象带有我正在寻找的标签,我想将其挑选出来并根据其标签将其添加到新列表中。然后在遍历该数组之后,我想为每个新列表获取一个随机元素并将其设置为活动

[SerializeField] private List<Transform> heads = new List<Transform>();
[SerializeField] private List<Transform> bodys = new List<Transform>();
[SerializeField] private List<Transform> arms = new List<Transform>();
[SerializeField] private Transform[] bodyParts;

private GameObject head;
private GameObject backpack;
private GameObject arm;

void Start()
{
    bodyParts = this.gameObject.GetComponentsInChildren<Transform>();
    for (int i = 0; i < bodyParts.Length; i++)
    {
        switch (bodyParts[i].tag)
        {
            case "Head":
                heads.Add(bodyParts[i]);
                break;

            case "Arm":
                arms.Add(bodyParts[i]);
                break;

            case "Backpack":
                backpacks.Add(bodyParts[i]);
                break;

            default:
                Debug.Log("Not relevant");
                break;
        }
    }
    SetActiveBodyPart(heads, head);

    SetActiveBodyPart(arms, arm);

    SetActiveBodyPart(backpacks, backpack);
}

void SetActiveBodyPart(List<Transform> whichBodyParts, GameObject whichBodyPart)
{
    if (whichBodyParts != null)
    {
        whichBodyPart = whichBodyParts[Random.Range(0, whichBodyParts.Count)].gameObject;
        if (!whichBodyPart.activeSelf)
        {
            whichBodyPart.SetActive(true);
        }
    }
    else Debug.Log("Nothing here...");
}

我在这一行遇到错误:

whichBodyPart = whichBodyParts[Random.Range(0, whichBodyParts.Count)].gameObject;

当我手动停用父级内的所有子游戏对象并开始游戏时,Unity 编辑器中的那些列表返回 0 但我希望输出为正整数

标签: c#arrayslistunity3d

解决方案


问题可能是您在尝试访问某个项目之前没有检查列表中是否有任何项目。Count您可以使用属性或扩展方法检查项目,如果我们将它与空条件运算符(如果左侧的对象是Any,它将返回)结合起来,我们可以这样做:nullnull

void SetActiveBodyPart(List<Transform> whichBodyParts, GameObject whichBodyPart)
{
    if (whichBodyParts?.Any == true)
    {
        whichBodyPart = whichBodyParts[Random.Range(0, whichBodyParts.Count)].gameObject;

        if (!whichBodyPart.activeSelf)
        {
            whichBodyPart.SetActive(true);
        }
    }
    else 
    {
        Debug.Log("Nothing here...");
    }
}

如果您想在日志中获得更准确的信息,另一种选择是分别检查每个条件:

void SetActiveBodyPart(List<Transform> whichBodyParts, GameObject whichBodyPart)
{
    if (whichBodyParts == null)
    {
        Debug.Log("whichBodyParts is null");
    }
    else if (!whichBodyParts.Any())
    {
        Debug.Log("whichBodyParts does not contain any items");
    }
    else
    {
        whichBodyPart = whichBodyParts[Random.Range(0, whichBodyParts.Count)].gameObject;

        if (!whichBodyPart.activeSelf)
        {
            whichBodyPart.SetActive(true);
        }
    }
}

推荐阅读