2
\$\begingroup\$

I'm writing a Text-RPG and I have set up a ScrollRect where new paragraphs and choices are added and removed at every turn. This makes the size of the Content change constantly, which I handle with a Content Size Fitter.

To prevent the player from losing track of the last paragraph he was reading before making a choice, I'd like to keep it in the same position relative to the screen no matter what changes in the Content. However, this is not possible due to the clamped setting of the ScrollRect's Movement Type. I want to keep the clamped behavior to prevent endless scrolling, but I need to find a way to make it work while keeping the last paragraph's position.

Here's a visual representation of what I'm trying to achieve:

Current Behavior (Wrong) Desired Behavior (Correct)

Setting the ScrollRect's Movement Type to unrestricted causes the behavior I'm looking for. However, I can't allow the content to be scrolled endlessly. If there is a workaround for clamping an unrestricted ScrollRect that could be a solution... I'd love to hear about it!

I've also considered instantiating an empty block that takes the size of the choices block to cover the space marked in red. However, that causes more problems since the player might select a choice while the scroll is not entirely at the bottom. I really don't know how to make that work.

\$\endgroup\$
6
  • \$\begingroup\$ Why not try adding new paragraphs first and then removing the select block? \$\endgroup\$ Commented Oct 19, 2022 at 6:14
  • \$\begingroup\$ The new paragraph will have a different size than the choices block, so there will still be movement in the ScrollRect content. \$\endgroup\$ Commented Oct 19, 2022 at 6:29
  • \$\begingroup\$ Maybe make the reading text and response choices separate elements. Or maybe calculate and remap "manually" the anchoredPosition of content. \$\endgroup\$ Commented Oct 19, 2022 at 7:39
  • \$\begingroup\$ On a second thought there is a chance it could be as simple as caching anchoredPosition of Content, do changes, restore to the cached anchoredPosition. \$\endgroup\$ Commented Oct 19, 2022 at 7:49
  • \$\begingroup\$ If the size of the new paragraph is too small (sometimes it might be just a word, such as "Success!") the content will still be clamped at the bottom, causing the movement I'm trying to avoid. I can apply the cached anchoredPosition but it won't work because of the forced clamped behavior. \$\endgroup\$ Commented Oct 19, 2022 at 9:03

2 Answers 2

0
\$\begingroup\$

An easy fix Would be to add a vertical or horizontal layout group on ViewPort->the parent of the content Object. And set Position accordingly.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Can you be more specific about what position settings should be used "accordingly"? \$\endgroup\$ Commented Jul 3, 2024 at 11:09
0
\$\begingroup\$

I seem to have had the exact same problem as you. I asked GPT-4o this question and it absolutely killed it, with the solution working out of the box. This surprised me because it isn't a typical algorithms question that LLMs excel at but a rather niche problem specific to Unity for which little online information exists.

GPT-4o response:

using UnityEngine; using UnityEngine.UI; public class ScrollRectFix : MonoBehaviour { public ScrollRect scrollRect; public VerticalLayoutGroup layoutGroup; public ContentSizeFitter contentSizeFitter; // Method to remove a child and fix the scroll position public void RemoveElementAndFixScroll(GameObject element) { StartCoroutine(RemoveElementAndFixScrollCoroutine(element)); } private IEnumerator RemoveElementAndFixScrollCoroutine(GameObject element) { // Disable layout components layoutGroup.enabled = false; contentSizeFitter.enabled = false; // Remove the element Destroy(element); // Wait until the end of the frame yield return new WaitForEndOfFrame(); // Re-enable layout components layoutGroup.enabled = true; contentSizeFitter.enabled = true; // Force layout rebuild LayoutRebuilder.ForceRebuildLayoutImmediate(layoutGroup.GetComponent<RectTransform>()); // Wait until the end of the frame to ensure layout is updated yield return new WaitForEndOfFrame(); // Reset the scroll position to the top scrollRect.verticalNormalizedPosition = 1f; // Optionally, add another yield here if you still experience issues // yield return new WaitForEndOfFrame(); // Additional adjustments if necessary } } 

It worked out of the box and the only change I needed to make was to change 1f to 0f (I needed to scroll to the bottom rather than the top).

Source: https://chatgpt.com/share/6e067eda-c775-48e3-89c9-a3f651be5e6e

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.