【问题标题】:ArgumentOutOfRangeException error Unity3D C# when trying to get a random element from a list after iterating through an array遍历数组后尝试从列表中获取随机元素时,ArgumentOutOfRangeException 错误 Unity3D C#
【发布时间】:2019-07-11 18:14:48
【问题描述】:

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

【问题讨论】:

  • 您目前不检查列表是否为空。所以如果whichBodyPart中有0个对象,你会尝试索引进去,任何索引都是无效的。
  • 快速学会调试程序代码会有很大帮助。
  • 所以我尝试添加whichBodyParts.Count &gt; 0,是的,它没有给我带来任何错误,而是给我带来了Nothing here...。似乎我与上面的代码有关。据我了解,因为我包含了bodyParts = this.gameObject.GetComponentsInChildren&lt;Transform&gt;(); 并且还将所有子对象设置为停用。也许这就是问题
  • @CodeCaster 不,Random.Range(0,1); 永远不会返回 1。Random.Range(int, int) 的上限 is exclusive
  • @Ruzihm 啊,浮动重载是不同的。我的立场是正确的。

标签: c# arrays list unity3d


【解决方案1】:

如果要在GetComponentsInChildren 的结果中包含停用的组件,则需要包含includeInactive 参数并将其设置为true。此外,将this.gameObject 放在GetComponentsInChildren 之前是多余的:

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...");

【讨论】:

  • ...GetComponentsInChildren&lt;Transform&gt;(true) 太棒了!我得到了它。非常感谢。
【解决方案2】:

问题可能是您在尝试访问某个项目之前没有检查列表中是否有任何项目。您可以使用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);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-22
    • 2019-08-22
    • 1970-01-01
    • 2018-03-06
    • 2018-10-19
    • 2018-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多