- Home /
Putting dictionary items in GUI ScrollView
I want to get items from my dictionary and put them in a scrollable box. The code I have below works fine so far. How do I access the objects related to each field in the scroll box? Is there a better method to do this with dictionaries?
public class Menu : MonoBehaviour {
public GameObject player;
public Vector2 position;
public Vector2 size;
private Vector2 OriginalPosition;
public Vector2 scrollPosition = Vector2.zero;
// Use this for initialization
void Start () {
player.GetComponent<PlayerStatus>();
OriginalPosition = position;
}
void OnGUI()
{
position = OriginalPosition;
scrollPosition = GUI.BeginScrollView(new Rect(10, 300, 100, 100), scrollPosition, new Rect(0, 0, 220, 200));
foreach(KeyValuePair<Items,int> pair in Inventory.Potions){
position.y += 30;
GUI.Box(new Rect(0, position.y, 100, 20), pair.Key.itemName + " : " + pair.Value);
}
GUI.EndScrollView();
}
}
I have no idea what you mean. You already access the objects in the dictionary!?!
Btw, for such things GUILayout is really nice since it automatically calculates the positions / sizes of all GUI elements.
Also why do you use a dictionary here? what does the int value mean? the count? It would be enough to give the item class a count field. When i really wanted to use a dictionary i would do it the other way round and use an int (the item ID) as key. Either way a Dictionary prevents you from storing the same thing several times. If that's what you want it's ok.
Still i'm not sure what you're asking here ;) Can you explain it a bit more in detail what's your problem or what you want to do?
I'm using a dictionary as an inventory. $$anonymous$$ey corresponds to an item object. value corresponds to the number of each item. Adding extra values for each key is not a problem for me, I've fixed that issue by overriding gethashcode and equals. I'd like to know how to retrieve each object and value from the dictionary after the adding them to the scrollview. for example: in my inventory.potions dictionary. I have (health potion : 2) and (mana potion : 3). They show up correctly in the scroll box. I'd like to know if there is a reference to each key in the scroll box. If so, how do I retrieve it? If my method doesn't provide a reference, how can get a reference onto the scroll box (or somewhere accessible) to my health potions and mana potions from my dictionary?
As far as count field goes. Is that better than my dictionary method?
Well, it depends on how you want it. A lot of games allow multiple "stacks" or the same type. That's not possible with a dictionary. If you don't need / want this, it's ok that way.
I'll write an answer ;)
can you explain what you mean by multiple stacks? like an example? $$anonymous$$y class "items" has several subclasses: potions, armor, weapons etc. are you saying I won't be able to add any of the subclasses together into one dictionary?
No, no that should be no problem as long as your Item has a unique Hash value. I just take $$anonymous$$ineCraft as example. You can have a "stack" of wood in your inventory. One stack is limited to 64 items so if you collect more wood it creates a new stack of the same type. When you want unlimited stacking of items it's ok.
Next example of $$anonymous$$inecraft ;) Weapons have unique properties especially the durability / health. That's why it's a non-stackable item, so you have to store multiple seperate items when you have more than one. In your case it all depends on your Hash function.
Answer by Bunny83 · Sep 02, 2012 at 01:39 PM
It seems you have trouble to wrap your head around the immediate GUI system in Unity ;)
Your code in OnGUI does not "create" a GUI, it just "displays" it. OnGUI is called every frame like Update. Well it's actually called multiple times per frame to process other events. The Event class is strongly connected to OnGUI. All the GUI function use the event class to determine the current event and perform the proper action.
Are you sure your item class is called "Items"? I used "Item" in my example below.
Here's an example:
void OnGUI()
{
GUILayout.BeginArea(new Rect(10, 300, 100, 100));
scrollPosition = GUILayout.BeginScrollView(scrollPosition);
foreach(KeyValuePair<Item,int> pair in Potions)
{
GUILayout.BeginHorizontal("box", GUILayout.Height(20)); // style the group like a box
GUILayout.Label(pair.Key.itemName + " : " + pair.Value);
if (pair.Value > 0)
{
if (GUILayout.Button("Reduce", GUILayout.Width(70)))
{
Potions[pair.Key] = Potions[pair.Key] - 1;
}
}
GUILayout.EndHorizontal();
}
GUILayout.EndScrollView();
GUILayout.EndArea();
}
This will display a button behind each item in the list. When you press the button, it will decrement the count of that element.
this sort of works but I get an out of sync exception. You can't edit items in a dictionary while iterating through it.
Sure, that's mainly an issue of the foreach loop. That's also a reason why a list would be better ;) You can modify the elements in the dictionary, but you can't remove or add them inside the foreach loop. Another problem is that $$anonymous$$eyValuePair is a struct, so the Value also can't be changed inside the forloop.
There are workarounds for deleting objects. For example storing the element you want to delete and remove it later:
Item removeThis = null;
foreach($$anonymous$$eyValuePair<Item,int> pair in Potions)
{
// [...]
if (GUILayout.Button("Remove", GUILayout.Width(70)))
{
removeThis = pair.$$anonymous$$ey;
}
// [...]
}
if (removeThis != null)
{
Potions.Remove(removeThis);
removeThis = null;
}
lol man that just seems like too much of a hassle. I think I'm just going to use your method and make a count field for my items class. thanks for your help!
Your answer
![](https://koobas.hobune.stream/wayback/20220613080518im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Putting Dictionary/List using foreach as buttons in a scroll view? 3 Answers
Create a Button Scrollview 0 Answers
How to hide GUI and chilren? 0 Answers
Multiple Cars not working 1 Answer