Other
How to enable only items which are vissible on screen - Unity UI
Hello,
I m using Unity 5.2.x ( 5.2.2 on Windows & 5.2.0 on Mac). I want to ask that is there any technique by which I can get a call back or something similar to OnBecameVisible () for Unity UI elements.
Problem I'm facing is I have a scroll-list which has 300+ elements and some scroll list have 600+ elements now on mobile device it is taking around 5 - 10 seconds to open the respective scroll-list by clicking on the 'Open Scroll-list button'. The reason behind this is the scroll-list have too many items which are taking time to load, once it loaded into memory then enable/disable is not much taking time. The solution I got is 'Enable only that items which are visible on screen, rest of the items in the scroll list must be disable/SetActive(false)' ( Same as in ezGUI or In NGui scroll-lists.
Is there is anybody who now how to achieve this thing.
One more Question I have. Is there are any type of in-built functions present for Specially unity UI for any type of Use. As we have OnMouseDown/Up/Drag , OnBecameInvisible/vissible??
Answer by Statement · Nov 01, 2015 at 11:58 AM
So the Renderer base class sends messages OnBecameInvisible and OnBecameVisible to the GameObject it sits on.
The CanvasRenderer class does not send any messages.
Note that CanvasRenderer is not a Renderer in the polymorphic sense. CanvasRenderer and Renderer extend from Component so they don't share functionality from each other.
I think you could benefit from studying the UI implementation at bitbucket.
Though if I understand your problem correctly, it would be pointless to look for messages OnBecameInvisible and OnBecameVisible because the point is to defer instantiation until the object is needed and if the object doesn't exist yet, how would it ever get a OnBecameInvisible? Perhaps you are thinking of making 600 empty game objects and if any of them become visible, create the item? How about not?
I think what you are looking for is called a virtual list view. I don't know of any existing virtual list view for Unity, but the idea is that virtual list views are used when you have a large number of items to view and for performance reasons won't create actual items for the view. Only create for the items that are in the view, and possible a back and forward cache.
Instead of creating 600 UI items, create only the items that could possibly be visible. Instead of loading 600 different textures (consider a scenario where you want to show all wearable hats in the game for example), only load the resources for what is visible and what probably will be visible soon (back/front cache).
Here's a fugly image trying to depict what I mean. Say you have a rect that can at most show 4 buttons at a time. Only have 4 buttons in your scene (managed by the virtual list view). When a button goes out of view, keep the resources it needs loaded in memory (if user swipe up/down we dont want lag). Unload resources when user navigates away from them (to preserve memory) and make them 100% virtual.
Note that the only UI/GameObjects here is the scrollview + 4 buttons. The rest is just memory.
An example:
When the virtual list view wants to view Item 200, update the contents of one of the buttons to match what item 200 represents. Maybe you set the text to "silly hat" and the texture to a very, very silly hat image. When the virtual list view wants to view item 204, item 200 is no longer visible, so it updates the contents to reflect item 204, a sissy hat, and repositions the button into view. When the virtual list view wants to view Item 340, we understand that we'll just reuse the buttons again (item 201-204 are no longer in view). Also item 200 - 204 are way far from item 340 so it would make sense to unload the assets for the image until you scroll back to items 200-204...
To clarify a little more: Each entry in the list view is a simple representation of the contents, not the actual contents.
struct VirtualItem
{
public string title;
public string texture; // Note: Not an actual texture!
}
Then you add those to the virtual list view...
virtualListView.Add("Silly Hat", "Hats/Silly");
virtualListView.Add("Sissy Hat", "Hats/Sissy");
virtualListView.Add("$$anonymous$$anly Hat", "Hats/CrocodileDundee");
// ...
When the virtual list view need to update the view, it can do something like cache.Load(item.texture); to load the texture or to reuse an existing texture. When the item is no longer in view, you can do something like cache.Unload(item.texture); The cache can decide for itself if the actual texture should be unloaded or not.
First of all thanks for this great appreciate able answer, Basically i had already used this method which you are calling virtual scroll list. I was labeling it as a reusable elements scroll-list.
Now the problem here is :- the component in which the all elements are present is moving more and more upwards or more and more downwards , other wise the components will not able to scroll. The solution of this is I have to write my own scroll list/ scroll rect component or to tweak original scroll rect component . I 'm not such a great coder yet & neither I have a time for this becz my deadline is very near. ( I'll research or work on this after this project )
But in the mean time the solution I got is just enabling the very few items in the scroll rect component is solving my problem . & in ezGui scroll list these things are already done. I wanna do the same for the in built scroll list. That's all.
Hope I'll do something to fix this. & Once again thanks a lot @Statement for this wonderful answer
the component in which the all elements are present is moving more and more upwards or more and more downwards
Yes, the scroll view is moving contents. Buttons are child of contents. Your script checks if any of the buttons go out of bounds (You have the Viewport Rect, the Content Rect and your Buttons Rect).
I added more buttons than should be just to make an illustration. The button that is outside of bounds does not need to exist. You can still calculate the position the button would had IF it existed. Also, you can calculate if that rect is not within the visible area and move the button from top to bottom, where the next button should appear. So in practice you have so many buttons that are visible, and invisible buttons are moved to where the next button will appear. It is possible to calculate this based on the above information.
Oh.. Thanks alot , sure I'll try this out .