IndexOutOfRangeException: Array index is out of range. ERROR

Hi, i’m making an Invetory GUI system from one game and i have this problem.

IndexOutOfRangeException: Array index is out of range.
Position.Controller.GetObjectsInBag(Int32 t) (at Assets/Scripts/Inventory/PositionController.js 105)… (etc)

And the line of the error is

return objectsInBag[t];

of the function

function GetObjectsInBag(t: int)
{
return objectsInBag[t];
}

This is the script i’m using for

var mouseTextureHandler : MouseTextureHandling;

private var buttonClicked : boolean = false; //mira si el boton está pinchado
private var objAttached : boolean = false; //verdadero cuando un objeto ha sido seleccionado del inventario

private var posBags : Vector2[]; //posiciones en la pantalla donde ban a estar situadas las bolsas
private var flagAvailable : Array;
private var indexBags : int;
private var toggleAllBags : boolean = false;

private var objectsInBag : GameObject[]; //representa todos los objetos en la bolsa.
private var lastSlotUsed : int = -1; // dice cual ha sido el ultimo slot pinchado
private var slotMovedFlag : boolean = false; //flag to control movement inside the bag array

function Start()
{
	objectsInBag = new GameObject[64]; //64 porque hay 4 bolsas y cada una tiene 16 espacios.
	flagAvailable = new Array();
	
	posBags = [Vector2(195,260), Vector2(195, 465), Vector2(385,260), Vector2(385,465)];
	for( var i = 0; i < posBags.length; i++)
	{
		flagAvailable.Push(true);
	}
	indexBags = 0;
}


function Update() // ESTA FUNCION SE UTILIZA PARA QUE AL PULSAR SHIFT + B SE ABRAN Y SE CIERREN TODAS LAS BOLSAS
{
	if(Input.GetKey(KeyCode.LeftShift)  Input.GetKeyDown(KeyCode.B)) //Pulsado Shift + B
	{
		for(var child : Transform in transform)
		{
			if(child.GetComponent(InventoryGrid) == null)
			{
				break;
			}
			if(toggleAllBags)
			{
				child.GetComponent(InventoryGrid).HideBag();
			}
			else
			{
				if(!child.GetComponent(InventoryGrid).BagIsBeingDisplayed()) //asegurarse que la mochila no esta abierta
				{
					child.GetComponent(InventoryGrid).ShowBag();
				}
			}
		}
		if(toggleAllBags)
			toggleAllBags = false;
		else
			toggleAllBags = true;
	}
}


//devuelve la posicion que está disponible para mostrar en la bolsa seleccionada
function GetPositionAvailable()
{
	var found : boolean = false;
	for(indexBags = 0; indexBags < flagAvailable.length; indexBags++)
	{
		if(flagAvailable[indexBags])
		{
			found = true;
			break;
		}
	}
	if(!found)
	{
		Debug.Log("ERROR: por favor añade mas posiciones en el  array posBags. ");
		return;
	}
	flagAvailable[indexBags] = false;
	return Vector3(posBags[indexBags].x , posBags[indexBags].y, indexBags);
}



function FreePosition(t: int)
{
	flagAvailable[t] = true;
}


function SaveObjectInInventory(obj : GameObject)
{
	for(var i : int = 0; i < objectsInBag.length; i++)
	{
		if(objectsInBag[i] == null)
		{
			objectsInBag[i] = obj;
			obj.transform.localPosition = Vector3.zero;
			obj.active = false;
			obj.transform.parent = transform;
			return;
		}
	}
}

function GetObjectsInBag(t : int)
{
	return objectsInBag[t];
}

function SetObjectInBag(t : int, obj : GameObject)
{
	objectsInBag[t] = obj;
}

function SetLastSlotUsed(t : int)
{
	lastSlotUsed = t;
}

function GetLastSlotUsed()
{
	return lastSlotUsed;
}

function SetSlotMovedFlag(val : boolean)
{
	slotMovedFlag = val;
}

function GetSlotMovedFlag()
{
	return slotMovedFlag;
}

function GetButtonClicked()
{
	return buttonClicked;
}

function SetButtonClicked(val : boolean)
{
	buttonClicked = val;
}

function GetObjectAttached()
{
	return objAttached;
}

function SetObjAttached (val : boolean)
{
	objAttached = val;
}

Thanks!!

Make sure that you only pass in a value to GetObjectsInBag from 0 to 63.

i think i dont really understand that (sorry for my english by the way)

GetObjectsInBag is the array where the objets are going to be save, when i click one object, it desapear from the screen but in the debug mode i can see that it is in the first position of this array.
Thanks!!!

In your Start you assign objectsInBag to be an array of size 64:

objectsInBag = new GameObject[64];

That means it has elements from 0 to 63 (64 entries but they start at 0). So if you try to access any entry outside of the range of 0-63, then it throws this “array index is out of range” error.

Maybe do this:

function GetObjectsInBag(t : int)
{
	Debug.Log("Accessing Object index: " + t);
	return objectsInBag[t];
}

See what entry index gets logged out before it crashes.

oh yes, i figured that is the problem but i don’t know which par of the code is trying to do that :s
EDIT: i think the -1 is invalid no? why is trying to acces that position?

Yeah, the -1 is invalid. The code you posted isn’t the code that calls GetObjectsInBag. I suggest you go through your game and find all the places that call the GetObjectsInBag function. If you have more than one place, put a Debug.Log statement before you call it with something like:

Debug.Log(“Calling GetObjectsInBag A”);

Then the second place that you find that calls it put:

Debug.Log(“Calling GetObjectsInBag B”);

Then the third place:

Debug.Log(“Calling GetObjectsInBag C”);

And so on. Then when you look at your log again, you’ll see something like:

Calling GetObjectsInBag B
Accessing Object index: -1

Then that way you know where it is that you’re passing in the wrong value. From there you can trace the logic back and see how exactly you end up with -1. If you can’t figure it out, try posting the calling code and we can take a look at it.

im going to pass you the other code by PM, and I’ll try to do what you have told me

FizixMan has told me that the problem is in MoveSlot function and LastSlotUsed but i cant find exactly the error :frowning:

up

You should post your source code for the other people here.

I tried explaining the crux of the problem, but maybe they can do a better job articulating it and finding an exact solution to it.

EDIT: once he posts it, I think it has to do with the fact that “LastSlotUsed” is -1 if there was no slot used yet. However, in the MoveSlot function, that -1 is then passed into GetObjectsInBag which naturally complains about getting object -1.

Thanks, here is the secon code

var bagName : String = "Pon un nombre a la bolsa";
var bagBtnName : String = "Nombre del boton de la bolsa";
var posBagBtn : Vector2 = Vector2(50,50); //posicion del boton de la bolsa

var slotSize : float = 40; // Este es el tamaño que va a tener la bolsa
var spacingBetweenSlots : float = 5;
var defaultTextureSlot : Texture;
var bagNumber : int; // dice que bolsa está enlazada a esta transformación.

private var numSlots = 16;
private var offsetBag : int; //eso es cuanto se va a mover el index lel prents bag array
private var showBag : boolean = false; //muestra o no muestra esta bolsa.
private var bagPos : Vector2;
private var indexOnController : int; //Representa un index para posicionar la bolsa.
private var tmpTexture : Texture;

private var ctrl : PositionController;



function Start ()
{
	offsetBag = bagNumber * numSlots;
	ctrl = transform.parent.GetComponent(PositionController); //el parent es para el inventory, que es el padre de las bolsas
	
	indexOnController = 0;
}





function OnGUI ()
{
	if(GUI.Button(Rect(Screen.width - posBagBtn.x, Screen.height - posBagBtn.y, slotSize,slotSize), bagBtnName)) //Pinta un boton, rectángulo.
	{
		ToggleBag();
	}
	
	if(showBag)
	{
		Bag(bagPos.x, bagPos.y, 185,200);
	}
}






function ToggleBag ()
{
	if(showBag) 
	{
		HideBag();
	}
	else 
	{
		ShowBag();
	}
}



function HideBag()
{
	showBag = false; 
	ctrl.FreePosition(indexOnController);
}



function ShowBag()
{
	showBag = true;
	var info : Vector3 = ctrl.GetPositionAvailable();
	indexOnController = info.z;
	bagPos = Vector2(info.x, info.y);
}



function BagIsBeingDisplayed()
{
	return showBag;
}



function Bag(posX : float, posY : float, sX : float, sY : float){
GUI.BeginGroup(Rect(Screen.width - posX, Screen.height - posY, sX, sY));
	GUI.Box(Rect(0,0, sX, sY), bagName);
	
	for(var i = 0; i < 4;  i++)
	{
		for(var j = 0; j < 4; j++)
		{
			if(ctrl.GetObjectsInBag(offsetBag + (4*i)+j) == null) //No hay objeto en ese SLOT, se pone la textura por defecto
			{
				tmpTexture = defaultTextureSlot;
			}
			else
			{
				tmpTexture = ctrl.GetObjectsInBag(offsetBag+(4*i)+j).GetComponent(ObjectInfo).iconTexture; //pone la textura del objeto
			}
			if(Input.GetMouseButtonDown(0))
			{
				ctrl.SetButtonClicked(false);
			}
			if(GUI.Button(Rect(slotSize*j + spacingBetweenSlots*(j+1), slotSize*i + spacingBetweenSlots*(i+1) + 15, slotSize, slotSize), tmpTexture))
			{
				ctrl.SetButtonClicked(true);
				if(ctrl.GetObjectsInBag(offsetBag+(4*i)+j) != null) //poner la textura a nuestro cursor del raton
				{		
					ctrl.mouseTextureHandler.SetCursor(ctrl.GetObjectsInBag(offsetBag+(4*i)+j).GetComponent(ObjectInfo).iconTexture);
					ctrl.SetObjAttached(true);
				}
					MoveSlot(offsetBag + (4*i)+j);
			}
		}
	}
	
	GUI.EndGroup();
}

function MoveSlot(indSlot : int){
	
	if(ctrl.GetObjectsInBag(indSlot) == null  !ctrl.GetSlotMovedFlag()){//case when we click in a new empty space (we are moving our item to a new one)
		ctrl.SetObjectInBag(indSlot, ctrl.GetObjectsInBag(ctrl.GetLastSlotUsed()));//assign the object to a new slot.
		ReleaseSlot(ctrl.GetLastSlotUsed());
		ctrl.SetSlotMovedFlag(true);
		ctrl.mouseTextureHandler.ReleaseCursorIcon();
		ctrl.SetObjAttached(false);
	} else if(ctrl.GetObjectsInBag(indSlot) != null  ctrl.GetObjectsInBag(ctrl.GetLastSlotUsed()) != null  !ctrl.GetSlotMovedFlag()){//swap two non-empty slots.
		var tmpObj : GameObject = ctrl.GetObjectsInBag(indSlot);
		ctrl.SetObjectInBag(indSlot, ctrl.GetObjectsInBag(ctrl.GetLastSlotUsed()));
		ctrl.SetObjectInBag(ctrl.GetLastSlotUsed(),tmpObj);
		ctrl.SetSlotMovedFlag(true);
		ctrl.mouseTextureHandler.ReleaseCursorIcon();
		ctrl.SetObjAttached(false);
	} else {
		ctrl.SetSlotMovedFlag(false);
	}
	ctrl.SetLastSlotUsed(indSlot);
}

function ReleaseSlot(index : int)
{
	ctrl.SetObjectInBag(index, null);
}

can you help me please putting the debug lines in the code? i don’t know where i have exactly to put it

anybody? tutorialis from design3.com and is the inventoy system

damn im getting crazy…

My best guess is that there is a bug in the code or something has been missed out.

private var lastSlotUsed : int = -1; // dice cual ha sido el ultimo slot pinchado

and it’s in this function somewhere.

function MoveSlot(indSlot : int){
	
	if(ctrl.GetObjectsInBag(indSlot) == null  !ctrl.GetSlotMovedFlag()){//case when we click in a new empty space (we are moving our item to a new one)
		ctrl.SetObjectInBag(indSlot, ctrl.GetObjectsInBag(ctrl.GetLastSlotUsed()));//assign the object to a new slot.
		ReleaseSlot(ctrl.GetLastSlotUsed());
		ctrl.SetSlotMovedFlag(true);
		ctrl.mouseTextureHandler.ReleaseCursorIcon();
		ctrl.SetObjAttached(false);
	} else if(ctrl.GetObjectsInBag(indSlot) != null  ctrl.GetObjectsInBag(ctrl.GetLastSlotUsed()) != null  !ctrl.GetSlotMovedFlag()){//swap two non-empty slots.
		var tmpObj : GameObject = ctrl.GetObjectsInBag(indSlot);
		ctrl.SetObjectInBag(indSlot, ctrl.GetObjectsInBag(ctrl.GetLastSlotUsed()));
		ctrl.SetObjectInBag(ctrl.GetLastSlotUsed(),tmpObj);
		ctrl.SetSlotMovedFlag(true);
		ctrl.mouseTextureHandler.ReleaseCursorIcon();
		ctrl.SetObjAttached(false);
	} else {
		ctrl.SetSlotMovedFlag(false);
	}
	ctrl.SetLastSlotUsed(indSlot);
}

FizixMan already gave you the answer.

You set
private var lastSlotUsed : int = -1;

But you never test if its -1 before using it.
You never set it to 0+ before you use it.

So maybe change that line to:
private var lastSlotUsed : int = 0;

or put in a test for <0

thanks fot the answers
Well, i have set private var lastSlotUsed : int = 0 and also in this function

if(Input.GetMouseButtonUp(0)  !buttonClicked  objAttached)
		{
				ReleaseObjectFromInventory(lastSlotUsed);
				lastSlotUsed = -1;
				objAttached = false;
		}

The only strange thing is that if get the objects in the bag, and i press the first one, nothing happends untill i don press it the second time…
or if i press other object in the bag, it switch with the first one, than y can selec whatever i want and move it wherever i want

THanks a loottt