Requesting array.length(Solved)

Hiya,

After searching I’ve discovered that you can’t request the length of an array. In other words if the array.length is 0, you can’t request stuff at index 0. likewise if the array.length is 10, you can’t request stuff at index 10.

So, quest is, if I have elements in this array at the length index or if the array only contains one element, how can I access them?

array length gives you its length.
but arrays in .net are 0 indexed so the valid indices are from 0 to array.length-1

Thanks. But OK so if the ‘last’ valid index is -1 of the array length, how do I ever access the element that’s at array.length?

If you make an array with 10 elements, you never access the 11th. index 0,1…9 is 10 elements.

This reminds me of Spinal Tap, and “but these go to 11! one louder” :smile:

I think what he wants to do is something along the lines of (and I’ve no idea if this would work):

var enemies : GameObject[];
enemies = GameObject.FindGameObjectsWithTag("Enemy");
var lastentry = enemies.length - 1;
doSomething(enemies[lastentry]);

Are you asking if you have an array of length 10 (so elements 0,1,2…8,9) and you want to add an 11th (the element at 10), you need to build a new array of a longer length, copy the entries over, then set your 11th entry.

I have an array of gameobjects and when a certain event happens a message is sent to all of the gameobjects in the array. The gameobjects then remove themselves from the array (which is part of another object).

The issue is that the last object left in the array doesn’t send the message to the array holding object, I assume because it’s at index array.length

This leaves a leftover object in the array which should be removed using the SelectionDetected

if (hit.collider.CompareTag ("EnemyShip")) {
			if (Input.GetButtonDown("Fire1")){
					for (var Ships in CurrentlySelected)
					Ships.GetComponent("MoveToClick").SendMessage("SelectionDetected", SendMessageOptions.DontRequireReceiver);
				} 
			}

OK As I’m finding increasingly often, I work out a fix after vocalising my thoughts in the forum :slight_smile: Somehow it seems to help clarify things to talk about it :slight_smile:

Here’s my - probably very clunky - workaround

		if (hit.collider.CompareTag ("EnemyShip")) {
			if (Input.GetButtonDown("Fire1")){
					for (var Ships in CurrentlySelected)
					Ships.GetComponentInChildren(LaserTurret).target = hit.transform;
						for(i = 0; i < CurrentlySelected.length; i++)
						{ 
							CurrentlySelected[i].GetComponent("MoveToClick").SendMessage("SelectionDetected", SendMessageOptions.DontRequireReceiver);
							if (CurrentlySelected.length == 1)
							{
							CurrentlySelected[0].GetComponent("MoveToClick").SendMessage("SelectionDetected", SendMessageOptions.DontRequireReceiver);
							}
						}
				} 
			}

There is never anything at array.length, ever, in any circumstance. By definition it’s impossible since indices start at 0. If you have an array of size 5, then the elements are at indices 0, 1, 2, 3, 4. That’s 5 elements.

That’s just sending the message twice to element 0 if the array length is 1.

–Eric

But this one goes up to 11… :slight_smile:

I see what you mean but it seems to fix the problem! Using this code the array depopulates as expected (i.e when you click on an object tagged EnemyShip, all objects in CurrentlySelected are removed), whereas with the code as it was before all but one object in the array was removed.
I’m sure you’re right and it’s happening by fluke, but why would that be?

EDIT : Interestingly, the code works with up to three objects in the array. If the array is over 4 in length, the code only depopulates half of them, and even odder, if the objects are in a row (which they are in my scene) it removes every other one in the row (like removes one, misses one, removes one, misses one etc from the row).

Er… Wha?

I think I may see the issue. Are you depopulating within the loop? This is dangerous because you’re incrementing through it at the same time. Look at it like this, say we populate an array like this (all pseudo-code mind you):

0 => a
1 => b
2 => c
3 => d

Then we loop through it and remove entries:

for (i = 0; i < array.length; i++)
{
	print(i + " -> " + array[i])
	remove(i);
}

As we cycle through, we keep resizing the array and rearranging our list.
After one cycle we see “0 → a” printed, and we’ve removed element 0, but the array looks like this now:

0 => b
1 => c
2 => d

Notice that everything has shifted up. In addition, the array length has shrunk by 1 which will be important later. But now our “i” variable has incremented to the value of “1”, so on our second cycle it prints “1 → c”, skipping element 0 (value “b”) altogether. Our array now looks like:

0 => b
1 => d

The “i” variable is now set to the value of 2. Additionally, the array has shrunk to a length of 2. Now when it re-evaluates the loop it checks if “i” is less than the array length (is 2 < 2), the answer is “no”, so it skips your last entry.

You have two options: rewrite your loop to look like this:

var originalLength = array.length;
for (i = 0; i < originalLength; i++)
{
	remove(0); //always remove the "first" element because the array keeps sizing down
}

Or loop in reverse:

for (i = array.Length - 1; i >= 0; i--)
{
	remove(i); //keeps removing the "last" entry as the array shrinks
}

Hopefully that makes sense; kinda hard for me to explain.

EDIT: Generally, for simplicity’s sake, you can opt not to alter the array while looping through it and wait until after to depopulate it:

for (i = 0; i < array.Length; i++)
{
	doStuff(array[i])
}

for (i = array.Length; i >= 0; i--)
{
	remove(i);
}

Kind of inefficient, but might make things easier to separate the operations.

Thanks FizixMan! Education rocks!

No problem! I’ve been there before. Keep plugging away!