ArgumentOutOfRange for seemling no reason

Sorry, but I am already quite fustrated with this error. It doesn’t even make any sense, I mean out of range?? What do you mean by “argument out of range”? Anyway here is the error:

ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
System.Collections.Generic.List`1[UnityEngine.GameObject].get_Item (Int32 index) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/List.cs:633)
EnemyMovement.Awake () (at Assets/Scripts/Controllers/EnemyMovement.cs:45)
UnityEngine.Object:Instantiate(Transform, Vector3, Quaternion)
EnemySpawn:Spawn(Transform) (at Assets/Scripts/EnemySpawn.cs:16)
WaveSpawner:SpawnWave(Wave) (at Assets/Scripts/WaveSpawner.cs:109)
WaveSpawner:Update() (at Assets/Scripts/WaveSpawner.cs:57)

The only one that really matters is EnemyMovement.Awake () (at Assets/Scripts/Controllers/EnemyMovement.cs:45) as that is the one that determines all the other ones. Here is the actual script:

    void Awake ()
    {
        PlayerManagerScript = FindObjectOfType<PlayerManager>();
        Enemy = GetComponent<EnemyStats>();
        Agent = GetComponent<NavMeshAgent>();

        PlayerAmount = PlayerManager.Instance.PlayerList.Capacity;
        Player.Capacity = PlayerAmount;
        for (int TargetNum = 0; TargetNum < PlayerAmount; TargetNum++)
        {
            Player.Insert(TargetNum, PlayerManager.Instance.PlayerList[TargetNum].transform);
            TargetStats.Insert(TargetNum, Player [TargetNum].GetComponent<PlayerStats>());
        }

        Agent.stoppingDistance = AttackDistance;

        InPursuitOf = -1;
        ForgetTimer = NormalForgetTime;
    }

This script was made about a week or two ago and I remember I had this same error at the time, and for some reason I got a stupid solution of adding a null variable to the Player list, and just removing afterwards. I did the same for TargetStats. But the error came back now as I tweaked around with the script, and I can’t figure out a way to solve it. I tried using Start () method instead of Awake () method, but then it still has this error but in different places:

ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
System.Collections.Generic.List`1[UnityEngine.Transform].get_Item (Int32 index) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/List.cs:633)
EnemyMovement.Search () (at Assets/Scripts/Controllers/EnemyMovement.cs:132)
EnemyMovement.Update () (at Assets/Scripts/Controllers/EnemyMovement.cs:57)

This is a non-sense error and it’s driving me crazy. It is not like NullReferenceException which normally is easy to fix, I have no idea what it even means.

1 Like

Here are some notes on IndexOutOfRangeException and ArgumentOutOfRangeException:

http://plbm.com/?p=236

I see a possible problem. Just setting the .Capacity of a list does not change what is in it. It is entirely a hint to the underlying system to reduce allocation calls.

I see you set the .Capacity to something, then iterate from 0 to Capacity - 1… unless you actually had valid data in ALL entries up to that .Capacity, you will get an AOR exception.

Reading that documentation, it looks like if you had more things in your array than you stated by setting .Capacity, that also throws an AOR exception.

I have never used the .Capacity property and it’s likely that 99.9% of game uses would never have a need for it.

Aren’t lists supposed to be easy to change the size of in contrast to arrays which are completely static? I thought .capacity was meant for that. If not, what are the other options? I just checked and couldn’t find one to change the size of a list.

Also, it used to work before, and the code earlier wasn’t very different from the one I posted (I actually don’t really remember how it worked, pretty sure it was very similar).

I also noticed a bunch of other scripts are also getting this same error (as you can see in the first error), it is like all of them just decided to stop working from now on.

You just call .Add() or .AddRange() to add elements to the end of a list, or else use .Insert() to jam one in.

And just to be pedantic :slight_smile: , arrays have an immutable size set at creation, but their contents can be changed at will.

1 Like

But how will I know how many elements I should add to the list without knowing it’s size?
That for () statement only works if it knows the size of the list.
And the list is supposed to have it’s size based on another list, not one put in the inpsector, otherwise I wouls just have used an array, but the first time I tried with arrays they didn’t work as they have a set immutable size of zero. And of course I can’t add content to an array with size 0.

Are you aware that much like Array.Length, the List class has a property called .Count?

You can bound your for() loop with the .Count property… it’s generally how things are done with lists.

Like I said, short of performance optimizations in the case of MASSIVE arrays (and I mean in the millions of elements), I can’t imagine using .Capacity for anything useful in game development.

You can also create a List by giving it a number in the constructor:

var myList = new List<string>( 47);

And that will make a list containing 47 items, all of them the value of default(string), which is of course null .

There is also another form of the List constructor that accepts an IEnumerable, so you can make a duplicate list pointing to all the same original objects with:

var mySecondList = new List<string>( myList);

The items are identical, but the list itself is different.

Let me change my question, I guess the first one didn’t include what I actually need.

How do I CHANGE the size of a list based on the size of another list, AND store this size in an integer? I need the size of Player to be the same as PlayerList in PlayerManager script, and I need to know such size to know how many times for () statement should loop.
I tried directly assigning one list as equal to the other, like the example you mentioned, but one list is a Transform while other is a GameObject, so it’s impossible to assign one as the other. And it wouldn’t be ideal using GameObjects in the EnemyMovement script because it only needs the transform, and there would be a massive waste of memory by using GameObjects. PlayerManager is also likely going to need the whole GameObject instead of just Transform as it might necessary later for other scripts.

BTW I forgot to mention, like Array.Lenght, List.Count is read only, so I can’t use that as I need to change the size of the list.

Nevermind… I just tried using .Count and it worked fine. Here is the script:

    void Awake ()
    {
        PlayerManagerScript = FindObjectOfType<PlayerManager>();
        Enemy = GetComponent<EnemyStats>();
        Agent = GetComponent<NavMeshAgent>();

        PlayerAmount = PlayerManagerScript.PlayerList.Count;

        for (int TargetNum = 0; TargetNum < PlayerAmount; TargetNum++)
        {
            Debug.Log("RIGHT:" + TargetNum);
            Player.Insert(TargetNum, PlayerManagerScript.PlayerList[TargetNum].transform);
            TargetStats.Insert(TargetNum, Player[TargetNum].GetComponent<PlayerStats>());
        }

        Agent.stoppingDistance = AttackDistance;

        InPursuitOf = -1;
        ForgetTimer = NormalForgetTime;
    }

Thanks for your support. I still find it not ideal though, there should be a way of converting GameObject lists to Transform lists more easily than having to make a for () statement and cycle through every single element in the list.

It is trivial enough to just write it once and never think about it again.

List<Transform> TransformListFromGameObjectList( List<GameObject> GOs)
{
 var t = new List<Transform>( GOs.Count);
 for (int i = 0; i < t.Count; i++)
 {
  if (GOs[i])
  {
    t[i] = GOs[i].transform;
  }
 }
 return t;
}

Once you start to think in terms of the available .NET API, things get easier.

1 Like

You can use Linq:

List<GameObject> goList;
List<Transform> transforms = goList.Select(go => go.transform).ToList();

but ultimately the computer is going to go through every element one by one no matter what, you’re just abstracting it from yourself as the programmer.

1 Like