- Home /
Inventory, simple and easy
I have made an inventory. Simple. You see an object in the game, clicks on it, and then you get that object in your inventory.
This is my inventory:
// Inventory.js
// This script manages the inventory and displays the inventory items in a grid pattern
// Attach to your Inventory Manager Object
// Based on the code posted by Der Dude on the Unity3D forums: http://forum.unity3d.com/viewtopic.php?t=11865
static var statInventory : Inventory1; // To set an instance of this script
enum SlotType {Items, Weapons, Logs, Empty}
// HELPER CLASSES
@System.Serializable // Our Representation of an InventoryItem
class InventoryItem
{
var itemName : String; // What the item will be called in the inventory
var itemIcon : Texture; // What the item will look like in the inventory
var itemDescription : String; // The description of the item
var slotType : SlotType; // What slot the item will fit in
}
private var inventory : InventoryItem[]; // Our master inventory (private)
private var contentArray : InventoryItem[]; // The array to contain the item being passed to and from the LootObject
var inventoryWidth : int; // the number of columns to display the inventory in
var inventoryLength : int; // the size of the inventory in total number of slots
var iconWidthHeight : int; // The pixel size (height and width) of an inventory slot
var spacing : int; // Space between slots (in x and y)
var offSet : Vector2; // The start position of the inventory
var emptySlot : Texture; // This will be drawn when a slot is empty
private var openInventoryWindow : boolean; // Controls OnGUI and opens/closes the inventory window
private var inventoryWindow : Rect; // The dimensions of the inventory window
private var currentLootableItem : LootObject; // The pointer to the current lootable item being processed
private var newLootableItem : LootObject; // The pointer to a new lootable item to be processed
function Awake ()
{ // Setup the initial states of the variables
statInventory = this;
inventoryWindow = new Rect (10, 10, Screen.width - 10, Screen.height - 10);
openInventoryWindow = false;
currentLootableItem = null;
inventory = new Array (inventoryLength); // Create & init the array to hold the inventory
for (var i : int = 0; i < inventory.length; i++)
{
inventory[i] = null;
}
}
function Update ()
{
if (Input.GetKeyUp (KeyCode.I))
{ // If the "i" key is pressed...
openInventoryWindow = !openInventoryWindow; // ... toggle the inventory window.
}
}
function OnGUI ()
{
// Inventory Window
if (openInventoryWindow) // If the "open inventory window" toggle is true
{
GUI.Window (1, inventoryWindow, DrawInventoryWindow, "Inventory"); // The title of this window could be passed as a String from the LootableItem
}
}
function DrawInventoryWindow () // The window function to draw the inventory window
{
if (GUI.Button (Rect (5,5,10,10), "")) // Left upper corner quit button
{
CloseInventoryWindow ();
}
var j : int;
var k : int;
var currentInventoryItem : InventoryItem; // Establish a variable to hold our data
var currentRect : Rect;
for (var i : int = 0; i < inventory.length; i ++) { // Go through each row ...
j = i / inventoryWidth; // ... divide by array by width to get rows...
k = i % inventoryWidth; // ... find the remainder by width to get columns...
currentInventoryItem = inventory[i]; // ... set this point in the matrix as our current point ...
currentRect = (new Rect (offSet.x + k * (iconWidthHeight + spacing), offSet.y + j * (iconWidthHeight + spacing), iconWidthHeight, iconWidthHeight));
if (currentInventoryItem == null) // ... if there is no item in the j-th row and the k-th column, draw a blank texture
{
GUI.DrawTexture (currentRect, emptySlot);
}
else
{
GUI.DrawTexture (currentRect, currentInventoryItem.itemIcon);
}
// If there is an item at this location and there is a button click...
if (currentInventoryItem != null && GUI.Button (currentRect, "", GUIStyle ("label")))
{
if (Input.GetMouseButtonUp (0)) // ... if that click is mouse button 0: see the description
{
GUIContent (" " + currentInventoryItem.itemDescription); // Get the description out
}
}
}
}
function CloseInventoryWindow ()
{
openInventoryWindow = false;
}
function AddItem (item : InventoryItem)
{
for (var i : int = 0; i < inventory.length; i ++) // Go through each row
{
if (inventory[i] == null) // If the position is empty..
{
inventory[i] = item; // ... add the new item....
return (true); // ... and exit the function.
}
}
Debug.Log ("Inventory is full");
return (false);
}
function ResizeInventory (newInventoryLength) // This code is never called at this point, but can be when you integrate it.
{
var oldInventory : InventoryItem[] = inventory;
inventory = new Array (newInventoryLength);
for (var i : int = 0; i < oldInventory.length; i++)
{
inventory[i] = oldInventory[i];
}
for (var j : int = oldInventory.length; j < inventory.length; j++)
{
inventory[i] = null;
}
}
This is my object that is loot able:
// LootableObject.js
// Make the GameObject "Lootable".
// This script will
// Attach this script to any GameObject that is "Lootable"
#pragma strict
private var theInventoryItem : InventoryItem; // The current contents of this lootable object
private var thisLootableItem : LootObject; // A reference to this instance of this script
private var clicked : boolean; // Trap for creating the current contents only once
private var canLoot : boolean; // Boolean to control TestDistance.
private var playerTransform : Transform; // A reference to the Player Transform
private var thisTransform : Transform;
var itemName : String;
var itemIcon: Texture2D;
var itemDescription : String;
private var Inventory : Inventory1;
function Start ()
{ // Setup the initial states of the variables
//itemName = the object name
itemName = this.gameObject.name;
//itemIcon will get selected in Unity
//itemDescription as well
var theInventoryItem : InventoryItem;
//Init thhe inventory item
theInventoryItem.itemName = itemName;
theInventoryItem.itemIcon = itemIcon;
theInventoryItem.itemDescription = itemDescription;
thisTransform = this.transform;
playerTransform = GameObject.FindWithTag("Player").transform;
thisLootableItem = this;
clicked = false;
}
function OnMouseDown()
{
Loot ();
}
function Loot ()
{
if (!clicked)
{ // If not yet clicked, check Loot Table
clicked = true;
}
//Add the item to the inventory
Inventory.AddItem(theInventoryItem);
theInventoryItem = null; //Set it to null
//Destroy the game object
Destroy(this.gameObject);
}
$$anonymous$$y question is why it doesn't work. I get an error with playing the game.
NullReferenceException: Object reference not set to an instance of an object LootObject.Start () (at Assets/Scripts/Inventory/LootObject.js:32)
This is the point:
theInventoryItem.itemName = itemName;
So how do I work this out...?
This tut shows you how to handle the basic operations of an inventory: https://www.youtube.com/watch?v=$$anonymous$$LaGkc87dDQ
Answer by Bunny83 · Jan 18, 2012 at 12:24 PM
I will summarise what i've found:
Your Inventory array is a native array, not the UnityScript "Array" class. To create a native array you have to do it like this:
inventory = new InventoryItem[inventoryLength];
In LootableObject's Start function you re-declare the "theInventoryItem" variable so it's not saved along with the class since it's now a local variable inside this function. Remove the
var
keyword, it should just betheInventoryItem = new InventoryItem();
.I don't get what's the use of
thisLootableItem
. What's the point of a member variable to hold the own instance? Just usethis
where you need it.
Answer by syclamoth · Jan 13, 2012 at 02:36 PM
Well, obviously it's because you haven't created an object there- you've only declared a variable. Declaring a variable creates an object-shaped 'slot' into which an object can fit- it doesn't automatically create the object to fit in it (unless it is a value type, which JS doesn't naturally support).
To fix this error, you need to change the line
var theInventoryItem : InventoryItem;
to
var theInventoryItem : InventoryItem = new InventoryItem();
then that part should work.
Yes it worked. Thanks. I now have another problem.
NullReferenceException: Object reference not set to an instance of an object LootObject.Loot () (at Assets/Scripts/Inventory/LootObject.js:57) LootObject.On$$anonymous$$ouseDown () (at Assets/Scripts/Inventory/LootObject.js:46) UnityEngine.Send$$anonymous$$ouseEvents:DoSend$$anonymous$$ouseEvents()
When I want to Loot an object, thus calling the Loot() method.
Answer by TheGreatHooD · Jan 18, 2012 at 11:51 AM
Doesn't work. Now its got a problem with the array.
NullReferenceException: Object reference not set to an instance of an object UnityScript.Lang.Extensions.get_length (System.Array a) Inventory1.AddItem (.InventoryItem item) (at Assets/Scripts/Inventory/Inventory1.js:120) LootObject.Loot () (at Assets/Scripts/Inventory/LootObject.js:60) LootObject.OnMouseDown () (at Assets/Scripts/Inventory/LootObject.js:49) UnityEngine.SendMouseEvents:DoSendMouseEvents()
I looked it up. It is this part:
for (var i : int = 0; i < inventory.length; i ++) // Go through each row
{
if (inventory[i] == null) // If the position is empty..
{
inventory[i] = item; // ... add the new item....
return (true); // ... and exit the function.
}
}
Where the bold the line is where it goes wrong. It states that the inventory no object is. That's weird because I made it with the awake call.
inventory = new Array (inventoryLength); // Create & init the array to hold the inventory
for (var i : int = 0; i < inventory.length; i++)
{
inventory[i] = null;
}
What the hell is going wrong?
Answer by Larry-Dietz · Jan 13, 2012 at 02:42 PM
The first thing I notice is that in the start method, 2 lines above the line giving you the error, you are re-declaring the variable theInventoryItem, and it is not getting assigned a value. This is the cause of the error. You have this variable already declared as private at the top of your script.
Removing the 2nd declaration would be the first step I would recommend. Leaving the 1st one will leave the variable available to the remaining methods in the script.
However, you are still going to get this error, as the variable is still not being assigned anything as far as I can see.
I am a c# coder, not Javascript, so I may be all wet here, but you need to use new to create a new instance of your InventoryItem object. Something like...
theInventoryItem = new InventoryItem;
Hope this is of some help. -Larry
Yes it worked. Thanks. I now have another problem.
NullReferenceException: Object reference not set to an instance of an object LootObject.Loot () (at Assets/Scripts/Inventory/LootObject.js:57) LootObject.On$$anonymous$$ouseDown () (at Assets/Scripts/Inventory/LootObject.js:46) UnityEngine.Send$$anonymous$$ouseEvents:DoSend$$anonymous$$ouseEvents()
When I want to Loot an object, thus calling the Loot() method.
Looks basically like another occurance of the same problem. You are creating a variable to hold the inventory, but not assigning it a value.
You have private var Inventory : Inventory1 creating the Inventory variable, but nothing assigning it.
Try setting it equal to a new Inventory1
Hope this helps, -Larry
HATE THE CO$$anonymous$$$$anonymous$$ENT PART! FUUU
Doesn't work. Now its got a problem with the array.
NullReferenceException: Object reference not set to an instance of an object UnityScript.Lang.Extensions.get_length (System.Array a) Inventory1.AddItem (.InventoryItem item) (at Assets/Scripts/Inventory/Inventory1.js:120) LootObject.Loot () (at Assets/Scripts/Inventory/LootObject.js:60) LootObject.On$$anonymous$$ouseDown () (at Assets/Scripts/Inventory/LootObject.js:49) UnityEngine.Send$$anonymous$$ouseEvents:DoSend$$anonymous$$ouseEvents()
I looked it up. It is this part:
function AddItem (item : InventoryItem)
{
for (var i : int = 0; i < inventory.length; i ++)
{
if (inventory[i] == null)
{
inventory[i] = item;
return (true);
}
}
Debug.Log ("Inventory is full");
return (false);
}
Where the bold the line is where it goes wrong. It states that the inventory no object is. That's weird because I made it with the awake call.
inventory = new Array (inventoryLength);
for (var i : int = 0; i < inventory.length; i++) { inventory[i] = null; }
Answer by TheGreatHooD · Jan 18, 2012 at 12:30 PM
Thanks for the comment.
I have an Inventory and an Lootable Object script. The Inventory script is attached to an empty game object and with the button I you can get the Inventory open. The LootableObject is a script to attach to the object that can get picked up. When I click, the Loot() function will get called, and the item is supposed to be added to the inventory (so in the inventory script) and then destroyed in the game world. It goes wrong on the point when I want to add the Item to the Inventory.