- Home /
Index out of range in while statement but I can't figure out how.
Hi, I need help with a while statement in a coroutine that gives me an error code; "ArgumentOutOfRangeException: Argument is out of range. Parameter name: index". The error points to this line:
while (selUnit.transform.position != movePath[i].transform.position)
What seems to happen is that the while-loop is always triggered the first time (regardless if I feed it 2 identical transform.positions or not), and when yielding back to the while statement it gives the error.
Now, I think I grasp the message means (index is out of range for the list movePath), but I just can't see how. movePath needs to be at least 2 items long to get past the if-statement and I've debugged it before and after the loop to make sure. selUnit is not null, and I've made sure by logging it aswell.
Any help in explaining why this doesn't work is much appreciated!
Here's my code;
IEnumerator moveTo(List<HexNode> movePath)
{
if (movePath.Count > 1)
{
PlayerInput pInput = GetComponent<PlayerInput>();
Unit selUnit = GetComponent<PlayerInput>().selUnit;
for (int i = 1; i < movePath.Count; i++)
{
pInput.selUnit.movePoint = pInput.selUnit.movePoint - movePath[i].moveCost;
if (pInput.selUnit.movePoint < movePath[i].moveCost)
{
Debug.Log("not enough movement points");
pInput.selUnit.storedPath.AddRange((movePath.GetRange(i, movePath.Count - i)));
break;
}
while (selUnit.transform.position != movePath[i].transform.position)
{
pInput.ismoving = true;
pInput.selUnit.transform.rotation = Quaternion.LookRotation(pInput.selUnit.transform.position - movePath[i].transform.position) * Quaternion.Euler(0, 90, 0);
pInput.selUnit.transform.position = Vector3.MoveTowards(pInput.selUnit.transform.position, movePath[i].transform.position, moveSpeed * Time.deltaTime);
movePath[i].unitOnHex = pInput.selUnit;
Destroy(movePath[i].selOnHex);
movePath[i].selOnHex = null;
if (0 < i)
{
movePath[i - 1].unitOnHex = null;
}
yield return new WaitForEndOfFrame();
}
}
pInput.ismoving = false;
}
else
{
Debug.Log("no movepath");
}
}
I'm still unsure as to why this issue occurs, but I've figured out a way to make the code work. Turns out that if I put this in the start of the function it'll run:
List<HexNode> movePath = new List<HexNode>();
movePath.AddRange(move);
Since I like learning - can someone explain why i need to instantiate the list in the function ? and why debug.log can get the elements of the list when the while-loop clearly can't?
Edit: I renamed the input parameter to move and made a new list called movePath because I'm a bit lazy.
Answer by tanoshimi · Oct 17, 2016 at 06:33 PM
If movePath has 2 elements in it, they'll be movePath[0] and movePath[1]. movePath[2] would be out of range. So you want movePath[i-1] (which, curiously, you use correctly elsewhere)
Wouldn't my initial check ( if (movePath.Count > 1) ) ensure that movePath in the nested for-loop has at least 3 elements? (should really require 2 thou, i have to change it to movePath.Count > 0).
movePath is returned from a pathfinding function where movepath[0] represents the units current position. I use for (i = 1) to skip the unit translating to its current position before continueing to the next tile (movepath[1]). I put in the initial check to ensure i > 1 in order to avoid index out of range errors.
I have tried feeding the function movepath with up to 10 elements in it, but I still get the same error on the same line, so that's not it I'm afraid.
Hmm. I might have lost the logic somewhat - your code is somewhat arcane ;)
Some other comments for you to investigate - not sure if they're helpful to solve the question at hand, but maybe they'll create a spark:
Within the whole
while (selUnit.transform.position != movePath[i].transform.position)
section, I don't see anything that modifies either selUnit.transform.position or movePath[i].transform.position. So, assu$$anonymous$$g you can get your code to compile, when do you expect this loop to end?You've got`if (0 < i)`at line 32. i starts at 1 and only increments, so this is always going to be true, no?
At line 29/30:
Destroy(movePath[i].selOnHex); movePath[i].selOnHex = null;
What's the point of these lines? It looks like you're trying to destroy an object reference, but you never seem to reference selOnHex anywhere.
Haha I guess it's a bit arcane. I'm new to C# and Unity, but It's quite fun and I'm learning as I go.
What I want is to move the selected unit (selUnit) to the first element in the duration of movespeed * Time.deltaTime. The loop ends when it runs out of elements in movePath or when selUnit runs out of movePoints.
Yes, you're right. Thats redundant, thanks.
Another function has previously drawn a path along movePath on the grid, so I want to delete the instantiated path-objects as the unit moves along. The second line is there because when destroyed they listed as missing in the inspector. I wanted to set them as null ins$$anonymous$$d.
I've just seen your declaration that selUnit = GetComponent<PlayerInput>().selUnit;
. So selUnit
and pInput.selUnit
are the same? It would be a lot easier to follow your code logic if you stuck to one or the other!
They're the same, and I agree. Thank you :)
Your answer
Follow this Question
Related Questions
Coroutine called in different instances 2 Answers
start coroutine everytime 2 Answers
Coroutine works in editor, but not in build Windows application 0 Answers
While loop 2 Answers
Coroutine loop not working 1 Answer