繁体   English   中英

遍历数组后尝试从列表中获取随机元素时出现ArgumentOutOfRangeException错误Unity3D C#

[英]ArgumentOutOfRangeException error Unity3D C# when trying to get a random element from a list after iterating through an array

问题:在遍历数组后尝试从列表中获取随机元素时,出现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,但我希望输出为正整数

问题可能出在您尝试访问一项之前,您没有检查列表中是否有任何项。 您可以检查的项目来Count的财产,或Any扩展方法,如果我们结合这与空条件操作符(这将返回null ,如果左侧的对象是null ),我们可以这样做:

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

如果要在GetComponentsInChildren的结果中包括停用的组件,则需要包括includeInactive参数并将其设置为true 此外,把this.gameObjectGetComponentsInChildren是多余的:

bodyParts = GetComponentsInChildren<Transform>(true);

要处理仍然获得空列表的情况,还应该包括避免索引到空列表的检查:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM