- Home /
Mysterious crash involving an array
I made a simple inventory system where you can drag and drop items inside the inventory screen. I have an array of GameObjects (items) and an array of Rect (rects) both the same size (32). "items" is used to access the inventory texture to use of each item, and "rects" is used to place a rectangle on that texture to detect mouse input.
Here is the relevant code :
function OnGUI () { // Inventory Screen is toggled if (isToggled) { // Inventory Screen Box GUI.Box (Rect (Screen.width/2+50, 50, Screen.width/2-100, Screen.height-100), "Inventory"); boxRect = Rect (Screen.width/2+50, 50, Screen.width/2-100, Screen.height-100);
// Begin rendering item textures in the inventory
for (var i = 0; i < 4; i++)
{
for (var j = 0; j < 8; j++)
{
// If the item exists in the array and hasn't been selected (or dragged), draw its texture in the original position
if (items[(8*i+j)] && items[(8*i+j)].gameObject.GetComponent (WeaponStats).drawOldPos == true
&& items[(8*i+j)].gameObject.GetComponent (WeaponStats).selected == false)
{
var texWidth = items[(8*i+j)].gameObject.GetComponent (WeaponStats).baseImage.width;
var texHeight = items[(8*i+j)].gameObject.GetComponent (WeaponStats).baseImage.height;
rects[(8*i+j)] = Rect (texWidth * j + Screen.width/2+60, Screen.height - (texHeight * i + 105), texWidth, texHeight);
GUI.DrawTexture (Rect (texWidth * j + Screen.width/2+60, (texHeight * i + 70), texWidth, texHeight),
items[i].gameObject.GetComponent (WeaponStats).baseImage, ScaleMode.StretchToFill, true);
}
// If the item exists...
if (items[(8*i+j)])
{
// If the mouse button is Down and the item is selected, the item texture follows the mouse
if (mDown && items[(8*i+j)].gameObject.GetComponent (WeaponStats).selected == true)
{
/* 1 */GUI.DrawTexture (Rect (Input.mousePosition.x - texWidth/2, Screen.height - Input.mousePosition.y - texHeight/2,
texWidth, texHeight), items[(8*i+j)].gameObject.GetComponent (WeaponStats).baseImage, ScaleMode.StretchToFill, true);
}
// If the item has been dragged and isn't selected anymore (MouseButtonUp after dragging the item),
// draw item texture where the mouse button has been released (guiPosition)
if (items[(8*i+j)].gameObject.GetComponent (WeaponStats).drawOldPos == false &&
items[(8*i+j)].gameObject.GetComponent (WeaponStats).selected == false)
{
/* 2 */GUI.DrawTexture (Rect (items[(8*i+j)].gameObject.GetComponent (WeaponStats).guiPosition.x - texWidth/2,
Screen.height - items[(8*i+j)].gameObject.GetComponent (WeaponStats).guiPosition.y - texHeight/2, texWidth, texHeight),
items[(8*i+j)].gameObject.GetComponent (WeaponStats).baseImage, ScaleMode.StretchToFill, true);
/* 3 */rects[(8*i+j)] = Rect (items[(8*i+j)].gameObject.GetComponent (WeaponStats).guiPosition.x - texWidth/2,
items[(8*i+j)].gameObject.GetComponent (WeaponStats).guiPosition.y - texHeight/2, texWidth, texHeight);
}
}
}
}
}
}
Everything works well, but if I try to select the last item that wasn't dragged, Unity crashes. So if I have 1 item in the inventory and I select it, it crashes. If I have 3 items, I can move any 2 items but moving a third one causes a crash.
Commenting the lines 1, 2 and 3 (see commented numbers in code above) prevents the crash from happening, but I obviously need those lines.
I hope I gave enough information. This problem caused me numerous headaches, so thanks for any help.
Answer by Cyclops · May 27, 2010 at 06:17 PM
I don't see anything specific that is a bug, but here is a bunch of random thought I had on how I would debug this. :) Maybe it will trigger some useful ideas.
At first it sounded like a fencepost, or off-by-one error, where you were using zero-based arrays as one-based arrays. But - you're checking if the array entry exists before using it, so that's out. But that leads me to ask if the array entry is valid - existence just means it isn't null. Maybe in some other part of the code, you Destroyed an object without removing it from the array? Or maybe it isn't fully created/initialized yet?
And I would re-write the code to assign both the GameObject and Component to temporary variables - both to avoid re-finding them multiple times, and to make it easier to debug.
Minor point - I'm not sure if your array is holding GameObjects, or Transforms (and as a Unity noob, I still get a bit hazy on those :) So this code may not be exactly correct. But try this code, and double-check everything for validity:
for (var j = 0; j < 8; j++) { GameObject tmpOb = items[8*i+j]; // or is it a Transform? if (tmpOb == null) continue;
// Component ws = tmpOb.gameObject.GetComponent(WeaponStats); // if Transform.
Component ws = tmpOb.GetComponent(WeaponStats);
if (ws == null)
{
Debug.Log("uh-oh...");
return;
}
// rest of code here.
}
Another preference of mine, is to check for item validity at the top of a loop or function, and doing a continue/return if something is invalid. This avoids nesting code, deeper and deeper.
Answer by Extrakun · May 27, 2010 at 12:21 PM
In your first if-block within the loop, you have this
GUI.DrawTexture (Rect (texWidth * j + Screen.width/2+60, (texHeight * i + 70), texWidth, texHeight),
items[i].gameObject.GetComponent (WeaponStats).baseImage, ScaleMode.StretchToFill, true**);
Do you mean
items[8*i+j]
instead of
items[i]
Also, maybe you should consider just calculating an offset like this
offset = 8*i+j
So the code could look cleaner (and helps to avoid typo)
Thanks, I didn't notice the typo, but it didn't resolve my problem unfortunately.
Your answer
Follow this Question
Related Questions
Array Help GameObject Length Inventory 1 Answer
HELP How to remove gameobject from Built-in Arrays 2 Answers
Which is better for an inventory system, Array or List? 0 Answers
Click on a button that is created post start. 0 Answers
How to go around creating inventory with new GUI (4.6 Beta)? 1 Answer