- Home /
Scrolling Inventory - Instantiate Buttons Too Slow [UI 4.6]
Hi there,
//==== What I'm Looking For ====//
I'm trying to make a popup scrolling inventory like this:
[ElderScrolls Online Inventory]
http://cdn.tentonhammer.com/sites/default/files/styles/large/public/257080.jpg?itok=qRxbwZAb
//==== What the Problem Is ====//
The problem is that when I instantiate the buttons, the frame rate drops and it takes longer to load, the more items it has to load into the scene for the inventory. This is already a problem at 10 items, nevermind 50. How can I make a scrollable inventory that can be sorted/categorised without this problem?
//==== What I Have ====//
At the moment I have 3 item category options which are individual lists:
var itemCategory1 : List.<Item> = new List.<Item>();
var itemCategory2 : List.<Item> = new List.<Item>();
var itemCategory3 : List.<Item> = new List.<Item>();
var itemCategorySelected : List.<Item> = new List.<Item>();
when I click on a button it will set the selected category to match the item category.
function ButtonSelectCategory1 ()
{
itemCategorySelected = itemCategory1;
LoadInvBoxs();
}
This is the function I use to instantiate the boxes. I've striped out setting values etc for offset to make it easier to read. The inventory Button prefab has a script attached that has an item variable that gets filled in depending on the item it's creating. So that when I click the button it can identify what item it represents.
function LoadInvBoxs()
{
itemCount = itemCategorySelected.Count; // sets the amount of items to match the number of items in the selected category.
itemPrefab = Resources.Load("UI/InvBox", GameObject); // sets the prefab to instantiate to the inventory Box Prefab.
// Sets variables for width, height, ratio, row count etc added in here.
var j : int = 0;
for (var i = 0; i < itemCount; i++)
{
if (i % columnCount == 0)
{
j++;
}
//create a new item, name it, and set the parent
var newItem = Instantiate(itemPrefab);
newItem.name = scrollableArea.gameObject.name + " item at (" + i + "," + j + ")"; // sets new objects gameobject name.
newItem.GetComponent(ItemInventoryData).item = itemCategorySelected[i]; // fills in the variables on the button to match itemCategorySelected.
newItem.transform.GetChild(0).GetComponent(Text).text = newItem.GetComponent(ItemInventoryData).item.name; // sets new buttons text to match name of the item it represents.
newItem.transform.parent = scrollableArea.gameObject.transform; // sets the parent.
newItem.GetComponent(UI.Button).onClick.AddListener(newItem.GetComponent(ItemInventoryData).ClickItem); // adds the function that the button should use when clicked.
// sets transform of the object and it's offset added in here.
}
}
Answer by Mmmpies · Feb 01, 2015 at 01:30 PM
The new UI does all this for you.
Create a Panel and Add Component for a ScrollRect, and Again to Add Component for a Mask.
Create a child panel and set the pivot to the middle top, if you're having problems finding the pivot you need pivot setting instead of center like this:
Now Add Component on that child panel and put on a Content Size filter. Set Vertical fit to minimum size.
Add Component again and put on a Grid Layout Group. You can change the settings to fit what you want. Lots of quick tutorials on YouTube if you get stuck.
Now get your menu itemPrefab and add a layout element to so you can set the minimum size for height and width.
Then just instantiate the prefabs and set the parent to be the child panel with the Grid Layout group. It'll just build it for you.
If you want a scroll bar just add one to the canvas and match that on the ScrollRect element.
You should add the prefabs to an array so you can delete them all easily.
To be honest I don't know why it's slowing down so much because your code looks OK from what I can see, the only thing I can think is your positioning code is slowing it down but letting the UI handle it all should give you the most streamlined code. After all it's written by the people at Unity themselves.
Hope it helps.
I had a go with that and you are correct that the script that is trying to calculate the placement was slowing it down, but the instantiating so many button is still a problem when I have 100 or more, which I will need. Any suggestions?
Well I'd probably need more info, how complex are your instantiated objects, do they have high res images on them? I'm surprised that it can't handle that many though. I haven't tried it myself but maybe I should as 100 doesn't seem excessive.
Are you just instantiating and allowing the GridLayout to do all the work, or do you still have some scripts acting on the items?
Hi again, Thank you for getting back to me. I've only used the standard unity ui button graphic, although I will need to add unique images per item later. I have also attached a script to each button that holds the variable for what item it represents and how many there are in the inventory stack. It's not a massively long delay, but I have 2 character Idle animations going on in the background and it freezes while it instantiates all the buttons and is very noticeable. There isn't anything else going on in the background apart from loading those items. Your help is very much appreciated!
I'll have a think but the problem is my menu is for a phone so the screen space is so limited I just open it full screen. For that I switch game time to 0 so the only thing running is the menu. Stops things attacking me when I can't see them.
So not only does the menu cover everything, so I can't see the animations in the background I also freeze time which, undoubtedly helps the UI load faster.
Answer by thefallengamesstudio · Apr 04, 2016 at 01:37 PM
Hi. We've ran into the same issue and developed our own utility that greatly increases performance. It's 5 bucks on asset store(see the video for comparisons) : https://www.assetstore.unity3d.com/en/#!/content/58158
In your case, you'd use a "row" prefab, meaning a prefab will contain an entire row of subitems, so on the outside you have a vertical scrollview containing items in a list, rather than a grid. This is a limitation because our solution only works on lists of items (not directly grids). But the workaround I've mentioned works great (we're using it).
We've allowed you two Advertising posts. Please no more.
There is a specific place on the forum where you can plug your product :)
Good luck.
Sorry. Didn't know I can't post this as an answer in multiple places. I do, however, think this will help folks searching for an asset like this. And this is indeed a valid answer. Anyone could've mentioned this asset in a comment (or even I from a different account). The simple fact that I'm posting this makes it an advertisement and I know it's not difficult to understand why... Sorry again. You can delete any other answers you think it's needed, if that's the rule :)
Its cool. Where-as advertising is not really allowed on the site, us mods tend to agree that a couple of posts is ok. Its a fine line though between useful answer and spam :P
When giving an asset as an answer it makes sense if a person is recommending someone else's Asset rather than promoting ones own. But it is a Grey Area.
If you want to find the latest and most relevant Question to post on, I'm sure one more will be fine.
Also, there is this section of the Forum which is geared towards promoting Asset Store products.