Anybody got ScrollRects to cooperate with dynamic content?

I’m trying to create a long scrolling list of elements, but the elements are created at runtime. They get added to a VerticalLayoutGroup, one after the other. But the layout group doesn’t change the actual size of their container, which means the ScrollRect can’t adjust the scrollable region accordingly.

Or, if that didn’t make sense, I’ll explain from a different angle - ScrollRects work perfectly when the object inside them that they are scrolling is a fixed size and bigger than the container, but I need one to work when there are a growing bunch of objects inside, stacked vertically.

Any suggestions?

1 Like

the elements youre loading into the VerticalLayoutGroup - are they of static size? like a container for whatever information youre displaying in them? If so, maybe you can dynamically change the height of the scroll rect based on how many containers are currently loaded in the VerticalLayoutGroup.

if NOT, and this is based primarily around varying lengths of text, if you know that your font size is static, you can approximate how many characters take up how much length vertically and change the Rect’s height based on that approximation equation.

seems like a good question, and it sounds like i’ll have to cross that bridge too at some point.

let me know if either of those ideas worked, Kylotan!

Use ContentSizeFitter alongside the layout component for that

3 Likes

theVirtunaut - The items I add could have a fixed size, but I want something more dynamic. See below…

ortin - Aha… if I add a ContentSizeFitter to the object contained in the ScrollRect, and set the VerticalFit to either MinSize or PreferredSize, it works. Thanks!

1 Like

Oh… except you now have to watch out for breaking things in the editor - if you remove things that are part of that object, it fails to position it correctly afterwards, and that brokenness persists into Play Mode and back again. You’ll need to reposition it manually after removing things that cause a size change.

In fact, it seems to apply any time the scrollable content is too small for the container - when I enter play mode, it moves it down to align against the bottom of the scroll rect, and stays there when I exit play mode. PosY starts off at -14.5 in edit mode, changes to -266.5 in play mode, and is still there atfterwards. But the scrollable object is anchored to the top left - changing its size (with the ContentSizeFitter) shouldn’t be changing its position. Looks like a bug to me.

1 Like

Works fine for me. So you probably should submit a bug with your project.

cool. so you got it working! basically…

I wouldn’t say it works, since there are some definite bugs in how these layout things are calculating the layout, not to mention in how they carry over the runtime layout changes back to edit-time. Today it seems to want to move the scrolled content either off the top or past the bottom of the scrollrect with half the content visible, and shows me a broken scrollbar which implies I can scroll in 2 dimensions but which does not scroll at all. Still some bugs here, some mine, some Unity’s.

Here are my latest findings, with screenshots attached.

I can start off with a scrollable area (green area) smaller than the scrollrect (pink area), manually positioned at the top.

Then I press play, and the scrollbar breaks, setting the handle to a 20x20 square (see unityscroll2.png)

I tried fixing it by setting the scrollbar position in script after adding a row, but it doesn’t respond to that; the scrollbar is clearly in a broken state anyway.

Any ideas what is going on here? Anybody else managed to break their scrollbars like this?

(It’s worth noting that the mobile-style “drag to scroll” functionality works ok. It’s just the scrollbar that’s gone crazy.)

As an aside, I originally had another problem where, if I add further rows to the scrollable area, it grows in height (as it has a vertical group to stack the contents vertically, and a content fitter to set the height accordingly), but it decides to scroll the area upwards slightly, instead of growing down into the scrollrect.


This is because it was keeping the scrollable area pivot in the same position as it started out at, ie. 29 pixels down from the top of the scrollrect. By moving the pivot to the very top of the scrollable area (ie. y=1) I stopped this from happening and the content now grows downwards. I thought I’d post this in case anybody else encounters a similar problem.

Kylotan, did you ever find a workaround for this or report a bug? I’m having similar issues, notably that dynamic content added to a Vertical Layout Group on a ScrollRect behaves very strangely unless the content exceeds the vertical size of the ScrollRect.

Most puzzling to me is the way, as you reported, that the Content of the ScrollRect is moved to the bottom of its rect during play mode despite being anchored up-left and does not reinitialize after exiting play mode. That is some strange sauce.

Sorry, I’ve not done much more work on this since this post, and was mostly hoping some updates would fix this sort of thing! I was given the impression (from other posts on this forum) that when you start mixing layout groups and anchors you start to get things working at cross-purposes because they both access the same properties, so maybe the internal algorithm needs tweaking.

Did you ever get to the bottom of this?

I also have a problem where “content size fitter”. When i first start the game after setting it up, it moves my text so that the middle of the text area is aligned with the middle of the scroll rect, getting the scroll bar to its middle, and it stays there after i stop the game. I love the rest of the UI but this is incredibly annoying.

Later edit:
A few minutes after i posted i found my solution:
I had to move the pivot point to the upper part of the text.
Now i see this was already suggested in a reply.
But nobody has time to read all the replies :slight_smile:

2 Likes

This guy:

Solves the problem in his tutorial. Essentially he changes the container’s size during population using RectTransform.offsetMin and RectTransform.offsetMax . I thought it was a neat solution.

A year later, I come back to Unity, update to 5.2.1f1… and this is still broken. Maybe in different ways.

I deleted my scrollbar and added a new one, and that’s fixed the dumb ‘scrollbar handle is a small white circle’ bug. Great. But then I was getting the warning that ‘Parent has a type of layout group component. A child of a layout group should not have a Content Size Fitter component’. Of course, this was not true, since I had no layout groups on the parent, but okay. So even though I now had a scrollbar of the correct size, scrolling no longer worked.

I dig around in this forum to find out that things have changed since 5.2 (ScrollRect + Content size fitter not working in 5.2 - Unity Engine - Unity Discussions) and that I need an extra object in there now (one which is barely documented and not really explained at all). But, okay, I add an extra ‘viewport’ object as a child of the one with the ScrollRect and a parent of the scrolling content. Adding the Content Size Fitter to this object fixes the problem and now I can scroll properly. Hurrah!

Oh, except it’s back to giving me the ‘Parent has a type of layout group component’ warning, now for the viewport object. But I can just ignore that if it’s still working.

Oh, except it’s no longer working, because it’s doing that dumb thing that I’ve only ever seen with the ‘new’ UI code (i.e. since 4.6 or whenever this new system appeared), where going from Edit to Play to Edit mode somehow changes things and what you see in Edit mode once you come back from Play mode is not how you left it before entering Play mode. Sometimes the first time I enter Play mode does nothing, but the second time breaks it, moving a component into a different position entirely. Absolute madness. GIF below to show this. (Exiting Play Mode the second time moves my content to the bottom, outside the visible area. The gif doesn’t show it, but if I go back into Play Mode a 3rd time, the text is invisible (because it’s off the screen), until I start scrolling, at which point it magically reappears.)

Seriously, this layout system is an unreliable and overcomplex disaster. It was too long coming in the first place and now we’re a year on and it’s still a shambles. Not happy. Is there any prospect of this being addressed in a way that isn’t going to continue to require the plethora of components and objects to achieve simple flexible layouts?

Incidentally it looks a lot like this bug - Unity Issue Tracker - [Canvas] Nested canvas is set and remains set to lower left corner after entering and exiting play mode - and although that one refers to nested canvases, the symptoms look very similar.

By the sounds of the UI bugs that exist I would suggest staying away from 5.2 until at least the next 2 patches. So 5.2.1p3 at minimum.

But, in terms of the new scroll rect stuff, I think you still want to keep all your content, your content size fitter and your layout group on the Content object and the viewport object is just parent to that (and child to the scroll rect) and has a mask on it. (If you create a new scroll rect from the UI menu you’ll see it’s set to generate the viewport with mask by default). I believe that viewport is meant to accomadate some kind of culling for performance. I see the same warning you mention about the content size fitter in 5.2 (I think it means the layout group on the same object, not necessarily the parent) but it doesn’t actually seem to stop working or cause issues that I can see, yet.

This type of bug has existed since Unity 4.6 - why would I trust that it’ll get fixed in 2 patches’ time?

Regarding where to put the content size fitter, yes, I had removed it again from the intermediate viewport object after posting the above. Doesn’t fix the ‘play mode can move things in edit mode’ bug which makes the environment unsuitable for development work, unfortunately.

The ContentSizeFitter makes no sense in general. I hope they can get it working as expected. It shouldn’t be difficult.

I get a warning from it too, but I have to ignore it because the placement seems correct.

Today’s update - it seems like somehow the Y values of the anchors on my scrollable content had been flipped relative to what I’d expect - min was (0, 1), max was (1,0). I certainly didn’t set these values, so I assume it’s from some sort of interaction between a ContentSizeFitter and the VerticalLayoutGroup components on this object. Either way, I’ve reset these anchor values to min=(0,0), max=(1,1) and the problem doesn’t seem to be recurring. Yet.