Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  4. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Repositioning ScrollRect through code. Bug or wrong method?

Discussion in 'Unity UI & TextMesh Pro' started by hamstar, Sep 25, 2014.

  1. hamstar

    hamstar

    Joined:
    Sep 25, 2013
    Posts:
    82
    I'm not sure why this script isn't working. Is it possible set the position of a ScrollRect in this way? I'm trying to scroll to the top on enable.

    Code (CSharp):
    1. private ScrollRect scrollRect;
    2. private bool ready = false;
    3.  
    4. void Awake() {
    5.     scrollRect = GetComponent<ScrollRect>();
    6.     if (scrollRect == null) {
    7.         Debug.LogError("GameObject does not have a ScrollRect component. GameObject name: " + gameObject.name + " tag: " + gameObject.tag);
    8.         Destroy(this);
    9.     }
    10. }
    11.  
    12. void OnEnable() {
    13.     // if we try to access scrollRect before Start, errors are thrown (scrollRect hasn't initialised yet?)
    14.     if (ready) {
    15.         scrollRect.normalizedPosition = Vector2.zero;
    16.         Debug.Log("scrollRect.normalizedPosition: " + scrollRect.normalizedPosition);
    17.         // log prints: scrollRect.normalizedPosition: (0.5, 1.0)
    18.     }
    19. }
    20.  
    21. void Start() {
    22.     ready = true;
    23. }
    Sorry if this is a duplicate post, I did do a search.

    Thanks.
     
  2. vptb

    vptb

    Joined:
    Jan 15, 2014
    Posts:
    28
    The top? So I guess you're doing a vertical scroll rect? Try using scrollRect.verticalNormalizedPosition = 0;
     
  3. hamstar

    hamstar

    Joined:
    Sep 25, 2013
    Posts:
    82
    No luck I'm afraid. Guess this must be a bug because it's not making any sense to me.
    Code (CSharp):
    1. scrollRect.verticalNormalizedPosition = 0;
    2. Debug.Log(scrollRect.verticalNormalizedPosition); // prints 1
    It says the value is 1, and yet the scroll position is about half way down.
     
  4. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,304
    Please file a bug with repro steps and repro project.
     
  5. Drowning-Monkeys

    Drowning-Monkeys

    Joined:
    Mar 6, 2013
    Posts:
    282
    do we have any update on this? When i try this same method, it's always inconsistent, and rarely goes and stays at the top. Sometimes it starts at the top, and self-propels itself to the middle, which is where it goes by default.

    EDIT: Sorry - just noticed these posts are from today. I will wait a little longer ;-)
     
  6. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,304
    If someone would post a case number here of the reported bug then we'd know the issue had been reported. If nobody have reported it to our bug tracker, then no amount of waiting is going to help.
     
  7. hamstar

    hamstar

    Joined:
    Sep 25, 2013
    Posts:
    82
    I only just submitted Case 636249.
     
    runevision likes this.
  8. korbain

    korbain

    Joined:
    Sep 11, 2013
    Posts:
    5
    In case anyone is wondering, in 4.6b20, scrollRect.verticalNormalizedPosition = 0 (for bottom) and scrollRect.verticalNormalizedPosition = 1f for top does works correctly.
     
  9. Ricks

    Ricks

    Joined:
    Jun 17, 2010
    Posts:
    647
    Same problem here. It doesn't work here with b21.

    Funny thing is, when I put the code
    Code (CSharp):
    1. scrollRect.normalizedPosition = new Vector2(0.0F, 1.0F);
    into the OnValueChanged method then it immediately scrolls to the top. But it doesn't scroll, until I do at least a minimal drag on the ScrollRect content. It totally ignores it if I manually try to set the value before dragging. Can someone confirm?
     
  10. authorthe

    authorthe

    Joined:
    Oct 28, 2014
    Posts:
    5
  11. Ricks

    Ricks

    Joined:
    Jun 17, 2010
    Posts:
    647
    I'm pretty sure it's the same issue.
    Sent a bugreport with example, case number 643604
     
    authorthe likes this.
  12. hamstar

    hamstar

    Joined:
    Sep 25, 2013
    Posts:
    82
    While things have improved with b21, there is still some weird behaviour. I get the feeling that the ScrollRect component, or other UI components, are modifying the scroll position in Start and/or OnEnable. So, if we try to alter the scroll position in either of these methods, the changes we make may be overwritten.

    In the end, I used a coroutine to change the scroll position on the next frame to avoid conflicting with other OnEnable/Start methods.

    Example:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4.  
    5. public class RepositionScrollRectOnEnable : MonoBehaviour {
    6.     private ScrollRect scrollRect;
    7.     private bool ready = false;
    8.  
    9.     void Awake() {
    10.         scrollRect = GetComponent<ScrollRect>();
    11.         if (scrollRect == null) {
    12.             Debug.LogError("GameObject does not have a ScrollRect component. GameObject name: " + gameObject.name + " tag: " + gameObject.tag);
    13.             Destroy(this);
    14.         }
    15.     }
    16.  
    17.     void OnEnable() {
    18.         // if we try to access scrollRect before Start, errors are thrown (scrollRect hasn't initialised yet?)
    19.         if (ready) {
    20.             StartCoroutine(ResetToTop());
    21.         }
    22.     }
    23.  
    24.     void Start() {
    25.         ready = true;
    26.     }
    27.  
    28.     IEnumerator ResetToTop() {
    29.         yield return null;
    30.         scrollRect.normalizedPosition = Vector2.one;
    31.     }
    32. }
     
    Last edited: Oct 29, 2014
    authorthe and Ricks like this.
  13. Ricks

    Ricks

    Joined:
    Jun 17, 2010
    Posts:
    647
    Thanks, that did the trick! A single "yield null" Coroutine before setting the position... o_O
     
    Last edited: Oct 29, 2014
  14. Ricks

    Ricks

    Joined:
    Jun 17, 2010
    Posts:
    647
    Ok, this is f... weird:

    You want to save the current ScrollPosition via the OnValueChanged() method into PlayerPrefs?

    Well you can save it, but the ScrollRect somehow "overwrites" the values on startup like this:
    from 0.0F to 0.49999F => reloads with 0.0F
    from 0.5F to 1.0F => reloads with 1.0F

    :mad:


    Edit: above error is also avoided if you save the ScrollPosition 1 frame after generating the buttons.
     
    Last edited: Oct 30, 2014
  15. FamerJoe

    FamerJoe

    Joined:
    Dec 21, 2013
    Posts:
    193
    It's because there are issues with OnValueChanged being called more than necessary. The bug has been filed. Also with the above problem with scrolling, indeed "on the next frame" is the only way I've found of getting around it -- same goes for Scrollbars as well.
     
  16. authorthe

    authorthe

    Joined:
    Oct 28, 2014
    Posts:
    5
    Thanks, Ricks!
     
  17. authorthe

    authorthe

    Joined:
    Oct 28, 2014
    Posts:
    5
    Thanks for the example, I was looking for something that would run once without any additional ongoing overhead - looks like that's what you've achieved here.
     
  18. MikeM1970

    MikeM1970

    Joined:
    Jun 4, 2014
    Posts:
    9
    I was also having an issue with getting my Scroll Rect to scroll to the bottom immediately after appending text to the Text content inside; setting the verticalNormalizedPosition to 0f seemed to scroll the Text mostly to the bottom, but never quite all the way. The coroutine trick worked like a charm. Many thanks!
     
  19. Fattie

    Fattie

    Joined:
    Jul 5, 2012
    Posts:
    335
    "It's because there are issues with OnValueChanged being called more than necessary."

    What a joke. As of Sept 2018, OnValueChanged is called every frame in most setups I've tried.

    It's just laughable.