Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
3
Question by oliver-jones · Feb 23, 2011 at 06:48 PM · guigridinventory

Place Inventory Into GUI Button Grid

--- EDIT --- (Illustration added)

Hello,

I'm working on a basic Inventory, so far, all it does is:

User selects a specific object from the scene (eg: knife), this is then added as a GUI button in the inventory.

All I'm struggling with is places the Items/GUI Buttons in a grid format. All that happens right now, is if I pick up a knife - a GUI button is added to the inventory, then if I pick up something else, that knife button is simply 'replaced' by that.

What I want, is:

User picks up item/object, this is then added to inventory as button. User then picks up another object, and a button is placed, say 50 pixels downward, and so on.

Here is an illustration to get an idea: alt text

Script:

var knife : GameObject; static var knifeInventory : boolean = false;

var password : GameObject; static var passwordInventory : boolean = false;

private var inventoryPanel : boolean = false;

var selGridInt : int = -1; var objGroup = new Array(GameObject); var objItemNames = new Array(String);

function Update(){ if(knifeInventory == true){ knife.gameObject.SetActiveRecursively(false); selGridInt ++; objGroup[selGridInt] = knife; objItemNames[selGridInt] = "Knife"; } else { knife.gameObject.SetActiveRecursively(true); }

 if(passwordInventory == true){
     password.gameObject.SetActiveRecursively(false);
     selGridInt ++;
     objGroup[selGridInt] = password;
     objItemNames[selGridInt] = "Password";
 }
 else{
     password.gameObject.SetActiveRecursively(true);
 }

}

function OnGUI(){ if(Input.GetButton("Jump")){ if(inventoryPanel == false){ if(GUI.Button(Rect(10,70,120,30),"Show Inventory")){ inventoryPanel = true; }
} else if(inventoryPanel == true){ if(GUI.Button(Rect(10,70,120,30),"Hide Inventory")){ inventoryPanel = false; }
} if(inventoryPanel == true){ //selGridInt = GUI.SelectionGrid (Rect (10, 120, 120, 400), selGridInt, objItemNames, 1); GUI.BeginGroup (new Rect (10, 120, 120, 400)); GUI.Box(Rect(0,0,120,400),""); GUI.Button(Rect(0,10,120,30), objItemNames[selGridInt]); GUI.EndGroup(); }

}
}

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
10
Best Answer

Answer by Peter G · Feb 27, 2011 at 05:07 PM

EDIT: After reading your edit, I think the Dictionary option is better suited for your needs. And the first code block should work without any problems. I got a harmless error when running, but it shouldn't be a problem.

First of all, you cannot create an array like this: new Array(GameObject). That isn't a possible argument. Logically, you want to store an object with a name so a dictionary makes the most sense because it associates a value (in this case a reference) with a Key such as its name. So I decided to do this thing called Debugging to find the problems with the script I posted earlier and it turns out that it works splendid. Go figure :). So I fixed the bugs (why it is string in C# and String in js is beyond me) and now it should work fine.

public var items = new System.Collections.Generic.Dictionary.<String,GameObject>(); //Create the dictionary full of a name and a GameObject associated with it. private var curItem : System.Collections.Generic.KeyValuePair.<String, GameObject>; //This will store the current item.

public var buttonHeight = 50; public var width = 100;

function AddItemToInventory (item : GameObject) { items.Add(item.name, item); }

function OnGUI() { var curIndex = 0;

     GUI.BeginGroup (new Rect (10, 120, 120, 400));

     for(var item : System.Collections.Generic.KeyValuePair.&lt;String, GameObject&gt; in items) {

         //iterate through all the items in the dictionary.
          var rect : Rect = new Rect(0, buttonHeight * curIndex, width, buttonHeight);
          //Create a rect for the button.  It is offset more for each item in the array.
          if(GUI.Button(rect, item.Key)) {
               curItem = item;             
               //USE ITEM
               RemoveItem(item);
               //if the user clicks the button, select it as the current item.
          }
          curIndex++;
          //increase the offset counter.
     }

     GUI.EndGroup();

}

//I added this function because I was getting an error deleting the KeyValuePair during the iterator function RemoveItem (item : System.Collections.Generic.KeyValuePair.<String, GameObject>) { yield WaitForEndOfFrame; items.Remove(item.Key); } //This code was in the comments, but I moved it up here so that everyone could see it.

function RemoveItem (item : GameObject) { yield WaitForEndOfFrame; items.Remove(item.name); }

This script should do exactly what you need. Call AddItemToInventory() to add an item. Then in the GUI, the script iterates through the dictionary and for each item it does the following:

  • Create a rectangle that will be our final box. Offset each time so that it isn't on top of the one before it.

  • Create the button. It simply displays the name of the item in the box.

  • If the user clicks the button, do whatever you want with it, then remove it from the Dictionary.

  • Then it won't show up in the list anymore. And all the items will move up accordingly.

I figured I leave the list up since I had originally posted it and someone might find it useful. This one creates 2 lists, one storing the object and another storing its name which is a strange design concept, but it would get the job done. It displays a GUI toolbar that will display all the names of objects in the list. But you would then have to do something accordingly and I don't think this way will do what you want as well as the other.

public var items : System.Collections.Generic.List.<GameObject>(); //Create a list of all the items in our inventory

private var itemNames : System.Collections.Generic.List.<string>(); //Create a list of all their names for the GUI.

public var curItemID : int; //Use this to find the item in your array.

function AddItemToInventory (item : GameObject) { items.Add(item); itemNames.Add(item.name); //fixed this line. }

function OnGUI() {

     GUI.BeginGroup (new Rect (10, 120, 120, 400));

     curItemID = GUI.Toolbar(someScreenRect, curItemID itemNames.ToArray() );
     //This will automatically add another box for each item you have

     GUI.EndGroup();

}

Comment
Add comment · Show 16 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image oliver-jones · Feb 28, 2011 at 02:14 PM 0
Share

Thanks for your help - but I'm getting a lot of errors, such as missing ; and (). I tried fixing most of it, Also get a "Name is not a member of UnityEngine.GameObject". Also "$$anonymous$$ identifier: Dictionary & $$anonymous$$eyValuePair. Thanks

avatar image Peter G · Feb 28, 2011 at 10:59 PM 2
Share
  1. that name should be lowercase...name. 2. AFAI$$anonymous$$ you can't use "using" in js. but I'm lazy and that is a lot to write. Try pasting that before all the generic objects, thats just dictionary and $$anonymous$$eyValuePair

avatar image Alec-Slayden · Mar 01, 2011 at 08:26 AM 0
Share

Peter's script seems to be in C#, Oliver, make sure you haven't saved it as a .js, as I think that'll confuse Unity.

avatar image Peter G · Mar 01, 2011 at 11:02 AM 1
Share

Believe it or not it is written in js. Unity3 added support for generic collections in javascript.

avatar image oliver-jones · Mar 03, 2011 at 11:45 PM 0
Share

Thanks Peter - I've given the first script a go, and I came across a few problems: When I pick up my first object (knife) - the button appears (good!), but when I then go and pick up a few more objects, their buttons do not appear until I click on the knife button. Its as if the knife button acts like a toggle on and off button for the rest of the buttons. The knife button does not disappear when I click on it - as for the rest, they work fine, until I click on the knife button, then everything is reset. Hope that makes sense.

Show more comments
avatar image
0

Answer by Scribe · Mar 01, 2011 at 09:06 PM

Don't know if this helps or not:

var inventory : Array; public var emptyTex : Texture; var iconWidthHeight = 20;

// Create the an 8x8 Texture-Array function Awake() { inventory = new Array(8); for( var i = 0; i < inventory.length; i ++ ) { inventory[i] = new Array(8); } }

function OnGUI() { var texToUse : Texture;

 //Go through each row 
 for( var i = 0; i &lt; inventory.length; i ++ ) 
 { 
     // and each column 
     for( var k = 0; k &lt; inventory[i].length; k ++ ) 
     { 
         texToUse = emptyTex;

         //if there is a texture in the i-th row and the k-th column, draw it 
         if( inventory[i][k] != null ) 
         { 
             texToUse = inventory[i][k];
         } 

         GUI.Label( new Rect( k*iconWidthHeight, i*iconWidthHeight, iconWidthHeight, iconWidthHeight ), texToUse );
     } 
 } 

}

Not that great at arrays myself and this script is not mine I found it here: http://forum.unity3d.com/threads/11167-Laying-out-Icons-In-an-inventory-that-will-rearrange-to-fit

hope this helps you

Scribe

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Scribe · Mar 01, 2011 at 09:33 PM 0
Share

these two might also help: the first makes use of the script in my previous post: http://forum.unity3d.com/threads/49202-Inventory-amp-Looting-based-on-Forum-Code?p=312325 and the other is another inventory system not really what your looking for in this answer but if you are making an inventory system then it might be useful later: http://forum.unity3d.com/threads/48290-just-another-inventory

avatar image
0

Answer by Flynn · Mar 02, 2011 at 07:26 PM

The GUI gets cleared every time OnGUI gets called, so any previous Button calls you made are lost forever. This is why your boxes appear to disappear -- your rendering focus changes as the selection goes up. OnGUI also gets called every render update, instead of every change. (As opposed to Flash, which remembers what you render, and can be configured to only update when you make changes to the UI). This is kind of inefficient but has it's benefits in the long run.

So, how can you accomplish what you want?

Say you have an array of strings that you want to draw in a grid. (Doing strings for simplicity, you can change it to whatever you want, and have the handling be slightly different.)

This code would render those as selectable buttons in a grid: (As testing, I suggest copying and pasting then tire code into a new script, and adding that script to an object, then running, to see how it runs)

Note that button "0" will be invisible as it is initially selected.

//Depending upon what array type you use, slightly different solutions may be needed. //I'll go ahead and use a normal JS array. var arrayOfStrings = new Array(); var selected = 0;//This is not used how you use it. It is the player-decided selection.

function Start() { //Initialize our vars. selected = 0; arrayOfStrings = new Array();

 //Add a whole bunch of strings from 0-50.
 for (var i = 0; i &lt; 50; i++)
 {
     arrayOfStrings.Add("" + i);
 }
 //Remove the 13th because it's unlucky.
 arrayOfStrings.RemoveAt(13);//All indexes still start at 0, but we can do 13 because we have the number "0" in the array.
 //Remove the last one because he slept in today.
 arrayOfStrings.RemoveAt(arrayOfStrings.length - 1);

 //Remove 30 because he marks the age you become old.
 //We don't want to become old.
 arrayOfStrings.Remove("30");

}

function OnGUI() { selected = DrawStringArray(arrayOfStrings, 7, new Vector2(50,25), selected);//Call oru helper function! :)

}

//Call this in OnGUI when you want your buttons to be displayed. function DrawStringArray(arr, rowLength, itemSize, sel) { //arr is an Array object //Row Length is how many items are displayed in a row. //itemSize is how large an item is. //sel is the currently selected item, and is not necissarry for basic function.

 for (var i = 0; i &lt; arr.length; i++)
 {
     //First, calculate the XY position.
     var x = 0;
     var y = 0;
     x = i%rowLength;//This basically loops the number back to 0 when it hits rowLength. (It's the remainder operator)
     y = Mathf.Floor(i/rowLength);//This means that every time i hits rowLength, y will be one greater. We Mathf.Floor it to make sure any decimal pointi s truncated -- Thereby making it snap, and not smoothly go down.
     var rect = new Rect(x*itemSize.x, y*itemSize.y, itemSize.x, itemSize.y);
     //From here on, you can do whatever you want, but I will continue programming just ot give an example

     if (sel == i)//We ae about to draw the selected one.
     {
         //DoSomethingSpecialWhichIAmNotCreativeEnoughToDoMySelf
     }
     else
     {
         sel = (GUI.Button(rect,arr[i])?i:sel);//This is an interesting way of do it. It is equivelant to:

         /*
         if (GUI.Button(rect,arr[i]) == true)
         {
             sel = i;
         }
         else
         {
             sel = sel;
         }
         */
     }

 }
 return sel;

}

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

No one has followed this question yet.

Related Questions

GUI grid of buttons issue. 1 Answer

UI: Dynamically sized inventory window with scroll 0 Answers

How to select a texture in an inventory? 0 Answers

Instantiating object from inventory 0 Answers

Mysterious crash involving an array 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges