Search Unity

Scroll View/Rect breaks on android

Discussion in 'UGUI & TextMesh Pro' started by Mr-Tomato, Feb 19, 2022.

  1. Mr-Tomato

    Mr-Tomato

    Joined:
    Apr 8, 2015
    Posts:
    3
    Hey, i made a game once in 2019 with unity 2019 and everything was good.
    I decided to make a small update to game, and upgraded to unity 2021.2.11f1 as well.

    For some reason i noticed the Scroll View/Rect breaks on Android when doing exactly this:
    Scrolling all the way down and then up all in one motion.

    if you just scroll down and stop and then scroll up, all good, if you dont scroll all the way down, all good.

    when the break happens, the content of scroll view is gone, and a big horizontal scrollbar appears, at this point only restart of the game fixes the issue.

    It doesnt happen in editor game, just on android build, and it didnt happen before in 2019.

    I did change one slight thing in UI though, the scroll view is child of a transform, and its child of another main transform(menu), and i changed its scale from 2 to 1.75(in x, y , z ).

    Very strange problem, if anyone faced something similar and knows, will appreciate some info :D
    Thanks

    Attaching pics of the issue, hierarchy, and components.

    scroll view in working state:
    upload_2022-2-20_0-18-42.png

    broken state:



    hierarchy of the menu:
    upload_2022-2-20_0-23-16.png

    the background transform(gray background) and parent of scroll view:

    upload_2022-2-20_0-24-10.png


    scroll view:

    upload_2022-2-20_0-24-27.png

    viewport:
    upload_2022-2-20_0-24-43.png

    content: (got limit of 5 pics damn)
    https://pasteboard.co/CsqQdEJ9gczE.png

    item:
    https://image.prntscr.com/image/ajXgmN4qS72U0hmfclQdCA.png

    scrollbar vertical:
    https://image.prntscr.com/image/ajXgmN4qS72U0hmfclQdCA.png

    scroll bar horizontal:(disabled)
    https://image.prntscr.com/image/ajXgmN4qS72U0hmfclQdCA.png
     
    Last edited: Feb 20, 2022
    vaxela_l likes this.
  2. Mr-Tomato

    Mr-Tomato

    Joined:
    Apr 8, 2015
    Posts:
    3
    vaxela_l likes this.
  3. realragnvaldr

    realragnvaldr

    Joined:
    Jul 21, 2019
    Posts:
    41
    I experience a similar problem and haven't found a solution yet:
    • I have an app with multiple scrollrects (chat, list with games, list with contacts, etc)
    • In the Unity editor there are no problems
    • Android builds with any Unity version later than 2020.3.13f1 are bugged
    • Scrolling then sometimes makes the contents of a scrollrect disappear
    • This can happen with any scrollrect in the app
    • When it happens in one scrollrect (e.g., chat) it does not affect other scrollrects (e.g., list with games)
    • The contents won't come back when the app rebuilds the page - the only way to get them back is to restart the app
    • The LogCat doesn't show anything suspicious before, during, or after the scrollrect contents disappear
    • After it happens, the app keeps working perfectly fine, except for the scrollrect contents being invisible
    EDIT:

    I figured out what the problem is and also made a simple solution

    The problem is that in ScrollRect.cs, the RectTransform position is sometimes set to NaN during scrolling. The cause of the problem is that Time.unscaledDeltaTime in the LateUpdate() method is sometimes 0 (which in turn causes a division-by-zero in the calculation of velocity - see here for another mention of the same problem). A solution is to make sure that deltaTime is never 0, which I did by replacing
    Code (CSharp):
    1. float deltaTime = Time.unscaledDeltaTime;
    in LateUpdate() with...
    Code (CSharp):
    1. float deltaTime = Mathf.Max(Time.unscaledDeltaTime, 0.015f);
    (0.015 = 15ms, which is similar to time of 1 frame)

    To be 100% safe, I also added a NaN check at the start of method SetContentAnchoredPosition:
    Code (CSharp):
    1. if (float.IsNaN(position.x) || float.IsNaN(position.y)) {
    2.   return;
    3. }
    4.  
    ... but that was probably unnecessary.

    Note that you cannot directly change ScrollRect.cs, because it's read-only, meaning that any changes you make will automatically be undone. What I did is to make a copy of ScrollRect.cs (called MyScrollRect.cs) and replace all ScrollRect's in my app with MyScrollRect.

    The long version
    I'm facing a very similar problem and have been looking for solutions for ages, but can't find anything at all on it.

    My app uses scroll rects at various places (chat contents, list of ongoing games, list of contacts, etc). Just as in your case, things always run fine in the editor, but problems appear on Android builds that were built with a recent version of Unity (for me, Unity LTS 2020.3.13f1 seems to be the last one that doesn't give problems - i've been stuck with that version for almost a year now because of this bug...).

    The problem that I get on Android builds with any Unity version later than 2020.3.13f1 is that *any* of the scroll rects in my app sometimes becomes empty during scrolling. After it happens, there is no way to get the contents back other than restarting the app (the contents don't come back even when the app rebuilds the contents of the scrollrect, such as when going to the chat with a different player).The error in one scroll rect does not affect other scrollrects. So when the contents of the chat page disappear, i can still scroll the list with ongoing games - until that one disappears too, but then i can still scroll the list with contacts, until it disappears - etc. Everything else in the app also keeps working fine.

    This can happen in any of the scrollrects in my app and at any time, although it seems to happen only when the content is scrolling. Other than that, there doesn't seem to be any systematic pattern and - annoyingly - the Android LogCat doesn't show *anything* suspicious just before it happens, when it happens, or after it happens (no warning, no error, no info message...). Here's an example log:

     
    Last edited: Apr 24, 2022
    vaxela_l likes this.
  4. vaxela_l

    vaxela_l

    Joined:
    Feb 20, 2018
    Posts:
    1
    His we have the same problem on here application , we upgrade from 2020 LTS to 2021.3.0f1 LTS
    The problem not appearing on all Android device !
    The position of the content was set to Nan

    Do you have plan to fix, the ScrollRect script in the LTS version of unity ?

    2021.3.0f1 : We can see that you are dividing by deltaTime.
    Code (CSharp):
    1.      protected virtual void LateUpdate()
    2.         {
    3.             if (!m_Content)
    4.                 return;
    5.  
    6.             EnsureLayoutHasRebuilt();
    7.             UpdateBounds();
    8.             float deltaTime = Time.unscaledDeltaTime;
    9.             Vector2 offset = CalculateOffset(Vector2.zero);
    10.             if (!m_Dragging && (offset != Vector2.zero || m_Velocity != Vector2.zero))
    11.             {
    12.                 Vector2 position = m_Content.anchoredPosition;
    13.                 for (int axis = 0; axis < 2; axis++)
    14.                 {
    15.                     // Apply spring physics if movement is elastic and content has an offset from the view.
    16.                     if (m_MovementType == MovementType.Elastic && offset[axis] != 0)
    17.                     {
    18.                         float speed = m_Velocity[axis];
    19.                         float smoothTime = m_Elasticity;
    20.                         if (m_Scrolling)
    21.                             smoothTime *= 3.0f;
    22.                         position[axis] = Mathf.SmoothDamp(m_Content.anchoredPosition[axis], m_Content.anchoredPosition[axis] + offset[axis], ref speed, smoothTime, Mathf.Infinity, deltaTime);
    23.                         if (Mathf.Abs(speed) < 1)
    24.                             speed = 0;
    25.                         m_Velocity[axis] = speed;
    26.                     }
    27.                     // Else move content according to velocity with deceleration applied.
    28.                     else if (m_Inertia)
    29.                     {
    30.                         m_Velocity[axis] *= Mathf.Pow(m_DecelerationRate, deltaTime);
    31.                         if (Mathf.Abs(m_Velocity[axis]) < 1)
    32.                             m_Velocity[axis] = 0;
    33.                         position[axis] += m_Velocity[axis] * deltaTime;
    34.                     }
    35.                     // If we have neither elaticity or friction, there shouldn't be any velocity.
    36.                     else
    37.                     {
    38.                         m_Velocity[axis] = 0;
    39.                     }
    40.                 }
    41.  
    42.                 if (m_MovementType == MovementType.Clamped)
    43.                 {
    44.                     offset = CalculateOffset(position - m_Content.anchoredPosition);
    45.                     position += offset;
    46.                 }
    47.  
    48.                 SetContentAnchoredPosition(position);
    49.             }
    50.  
    51.             if (m_Dragging && m_Inertia)
    52.             {
    53.                 Vector3 newVelocity = (m_Content.anchoredPosition - m_PrevPosition) / deltaTime;
    54.                 m_Velocity = Vector3.Lerp(m_Velocity, newVelocity, deltaTime * 10);
    55.             }
    56.  
    57.             if (m_ViewBounds != m_PrevViewBounds || m_ContentBounds != m_PrevContentBounds || m_Content.anchoredPosition != m_PrevPosition)
    58.             {
    59.                 UpdateScrollbars(offset);
    60.                 UISystemProfilerApi.AddMarker("ScrollRect.value", this);
    61.                 m_OnValueChanged.Invoke(normalizedPosition);
    62.                 UpdatePrevData();
    63.             }
    64.             UpdateScrollbarVisibility();
    65.             m_Scrolling = false;
    66.         }

    2020.2.1f1 : You are not dividing
    Code (CSharp):
    1.     protected virtual void LateUpdate()
    2.     {
    3.       if (!Object.op_Implicit((Object) this.m_Content))
    4.         return;
    5.       this.EnsureLayoutHasRebuilt();
    6.       this.UpdateBounds();
    7.       float unscaledDeltaTime = Time.unscaledDeltaTime;
    8.       Vector2 offset = this.CalculateOffset(Vector2.zero);
    9.       if (!this.m_Dragging && (Vector2.op_Inequality(offset, Vector2.zero) || Vector2.op_Inequality(this.m_Velocity, Vector2.zero)))
    10.       {
    11.         Vector2 position = this.m_Content.anchoredPosition;
    12.         for (int index = 0; index < 2; ++index)
    13.         {
    14.           if (this.m_MovementType == ScrollRect.MovementType.Elastic && (double) ((Vector2) ref offset)[index] != 0.0)
    15.           {
    16.             float num1 = ((Vector2) ref this.m_Velocity)[index];
    17.             float elasticity = this.m_Elasticity;
    18.             if (this.m_Scrolling)
    19.               elasticity *= 3f;
    20.             ref Vector2 local1 = ref position;
    21.             int num2 = index;
    22.             Vector2 anchoredPosition = this.m_Content.anchoredPosition;
    23.             double num3 = (double) ((Vector2) ref anchoredPosition)[index];
    24.             anchoredPosition = this.m_Content.anchoredPosition;
    25.             double num4 = (double) ((Vector2) ref anchoredPosition)[index] + (double) ((Vector2) ref offset)[index];
    26.             ref float local2 = ref num1;
    27.             double num5 = (double) elasticity;
    28.             double num6 = (double) unscaledDeltaTime;
    29.             double num7 = (double) Mathf.SmoothDamp((float) num3, (float) num4, ref local2, (float) num5, float.PositiveInfinity, (float) num6);
    30.             ((Vector2) ref local1)[num2] = (float) num7;
    31.             if ((double) Mathf.Abs(num1) < 1.0)
    32.               num1 = 0.0f;
    33.             ((Vector2) ref this.m_Velocity)[index] = num1;
    34.           }
    35.           else if (this.m_Inertia)
    36.           {
    37.             ref Vector2 local3 = ref this.m_Velocity;
    38.             int num8 = index;
    39.             ((Vector2) ref local3)[num8] = ((Vector2) ref local3)[num8] * Mathf.Pow(this.m_DecelerationRate, unscaledDeltaTime);
    40.             if ((double) Mathf.Abs(((Vector2) ref this.m_Velocity)[index]) < 1.0)
    41.               ((Vector2) ref this.m_Velocity)[index] = 0.0f;
    42.             ref Vector2 local4 = ref position;
    43.             int num9 = index;
    44.             ((Vector2) ref local4)[num9] = ((Vector2) ref local4)[num9] + ((Vector2) ref this.m_Velocity)[index] * unscaledDeltaTime;
    45.           }
    46.           else
    47.             ((Vector2) ref this.m_Velocity)[index] = 0.0f;
    48.         }
    49.         if (this.m_MovementType == ScrollRect.MovementType.Clamped)
    50.         {
    51.           offset = this.CalculateOffset(Vector2.op_Subtraction(position, this.m_Content.anchoredPosition));
    52.           position = Vector2.op_Addition(position, offset);
    53.         }
    54.         this.SetContentAnchoredPosition(position);
    55.       }
    56.       if (this.m_Dragging && this.m_Inertia)
    57.       {
    58.         Vector3 vector3 = Vector2.op_Implicit(Vector2.op_Division(Vector2.op_Subtraction(this.m_Content.anchoredPosition, this.m_PrevPosition), unscaledDeltaTime));
    59.         this.m_Velocity = Vector2.op_Implicit(Vector3.Lerp(Vector2.op_Implicit(this.m_Velocity), vector3, unscaledDeltaTime * 10f));
    60.       }
    61.       if (Bounds.op_Inequality(this.m_ViewBounds, this.m_PrevViewBounds) || Bounds.op_Inequality(this.m_ContentBounds, this.m_PrevContentBounds) || Vector2.op_Inequality(this.m_Content.anchoredPosition, this.m_PrevPosition))
    62.       {
    63.         this.UpdateScrollbars(offset);
    64.         UISystemProfilerApi.AddMarker("ScrollRect.value", (Object) this);
    65.         this.m_OnValueChanged.Invoke(this.normalizedPosition);
    66.         this.UpdatePrevData();
    67.       }
    68.       this.UpdateScrollbarVisibility();
    69.       this.m_Scrolling = false;
    70.     }

    @unity_griendeau
     
    Last edited: Apr 29, 2022
  5. Grazer2

    Grazer2

    Joined:
    Jun 20, 2011
    Posts:
    86
    Also affecting us on iOS. Pretty wild bug to have in the engine. We're using 2020.3.32f1. 2020.3.33 doesn't have it fixed either according to the release notes. Unity-Team: Please fix!
     
    lntoan123 likes this.
  6. Taggler

    Taggler

    Joined:
    Apr 13, 2018
    Posts:
    6
    We also have this issue on and off. Please fix this on LTS versions.
     
    lntoan123 likes this.
  7. farquleetbraincord

    farquleetbraincord

    Joined:
    May 17, 2023
    Posts:
    1
    You just have to import ImputSystem From Package Manager and your issue becomes the fix