Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Access scrollbar.value not possible through code?

Discussion in 'UGUI & TextMesh Pro' started by RalliantoDeLaVega, Dec 2, 2014.

  1. RalliantoDeLaVega

    RalliantoDeLaVega

    Joined:
    Jan 30, 2014
    Posts:
    45
    (We are talking UI from unity 4.6) I finally made a scrollrect with a scrollbar, and some content, masked the rest out and it's pretty neat. What's not so neat is the scrollbar start in the middle of the view, i want it to start at the top, with the first element, and then you can scroll down. This position is controlled by Scrollbar.value , but it seems i can't access it through code. I tried both Awake(), Start() and OnEnable() like this:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4.  
    5. public class ScrollbarStartTop : MonoBehaviour {
    6.  
    7.     Scrollbar bar;
    8.  
    9.     void Awake()
    10.     {
    11.         bar = gameObject.GetComponent<Scrollbar>();
    12.         bar.value = 1;
    13.     }
    14.  
    15.     void Start()
    16.     {
    17.         bar = gameObject.GetComponent<Scrollbar>();
    18.         bar.value = 1;
    19.     }
    20.  
    21.     void OnEnable()
    22.     {
    23.         bar = gameObject.GetComponent<Scrollbar>();
    24.         bar.value = 1;
    25.     }
    26. }
    None of these seems to have any effect on the scrollbar value, it set itself to 0.5 when game starts. But if i do:

    Code (CSharp):
    1.  
    2.     void Update()
    3.     {
    4.         bar = gameObject.GetComponent<Scrollbar>();
    5.         bar.value = 1;
    6.     }
    7. }
    It works, but... then you cant scroll since the scrollbar wont be able to move.
    (Setting the value in the inspector, dosent have any effect, when the game starts, it sets automatically to 0.5)

    Is this a bug, or do i do something wrong?
     
    Last edited: Dec 2, 2014
  2. lilymontoute

    lilymontoute

    Joined:
    Feb 8, 2011
    Posts:
    1,181
    Have you set the scrollbar's value to 1 in the inspector? If you're making the scrollbar dynamically, you may want to wait a frame (turn Start into a coroutine and yield one frame) then set the position. It sounds like an order-of-execution issue going on there.
     
    hosseinAmini likes this.
  3. RalliantoDeLaVega

    RalliantoDeLaVega

    Joined:
    Jan 30, 2014
    Posts:
    45
    I am making the content of the scrollrect dynamically yes.
    I tried to set value to 1 in the inspector, but it still sets itself to 0.5 when game starts.

    I tried as you said:
    Code (CSharp):
    1. public class ScrollbarStartTop : MonoBehaviour {
    2.  
    3.     Scrollbar bar;
    4.  
    5.     public void Start()
    6.     {
    7.         wait();
    8.     }
    9.  
    10.     public IEnumerator wait()
    11.     {
    12.         Debug.Log("Now its called");
    13.         yield return new WaitForSeconds(1);
    14.         bar = GetComponentInChildren<Scrollbar>();
    15.         bar.value = 1;
    16.         Debug.Log("Now its setted");
    17.     }
    18.  
    19. }
    But didnt work, didnt even log anything in the debug window. Can you provide an example code for what you mean?
     
    Last edited: Dec 2, 2014
  4. lilymontoute

    lilymontoute

    Joined:
    Feb 8, 2011
    Posts:
    1,181
    Code (CSharp):
    1. public class ScrollbarStartTop : MonoBehaviour {
    2.  
    3.     Scrollbar bar;
    4.  
    5.     public IEnumerator Start()
    6.     {
    7.         Debug.Log("Now its called");
    8.         yield return null; // Waiting just one frame is probably good enough, yield return null does that
    9.         bar = GetComponentInChildren<Scrollbar>();
    10.         bar.value = 1;
    11.         Debug.Log("Now its setted");
    12.     }
    13.  
    14. }
    15.  
    should do the trick.
     
    Lokesh2022, aloften, pranta15 and 5 others like this.
  5. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    When a Scrollbar is linked to a ScrollRect, the Scrollbar value is linked to the scrolling of the ScrollRect.

    If the content inside the ScrollRect is smaller than the ScrollRect rect, then the scroll position is essentially undefined, and can be overwritten by the ScrollRect to be some "random" value.

    When a Scrollbar is linked to a ScrollRect, it's generally advised to modify the scrolling by setting the anchoredPosition of the content rather that trying to go through the Scrollbar, since the anchoredPosition is unambigously defined while the Scrollbar value is not always.

    Another thing to keep in mind: In case you use Auto Layout inside your content (like a ContentSizeFitter) the actual size of the content isn't calculated until just before the first frame is rendered. If you want to force it to be calculated earlier, you can call Canvas.ForceUpdateCanvases: http://docs.unity3d.com/ScriptReference/Canvas.ForceUpdateCanvases.html
     
    Zentm, Vedmate, Furjoza and 4 others like this.
  6. RalliantoDeLaVega

    RalliantoDeLaVega

    Joined:
    Jan 30, 2014
    Posts:
    45
    Indeed that did the trick, thx (y)

    But I will go for the "propper" way, and set the anchoredPosition of the content. (But why not control the start position of the scrollbar... in the scrollbar?)

    The height of the panel, which is the content of the scrollrect, is calculated just after the panel has been filled with buttons with a foreach loop.
    Code (CSharp):
    1. containerRectTransform.sizeDelta = new Vector2(width, itemCount * 32);
    I currently have 4 elements, so i got 4 buttons and a height at 128. When the scrollbar is at top (which i want), it's position is at -14 and when it's at it's lowest point, it's position is 14. How does -14 and 14 relate to the height 128 ? :p -Anyway, if i set the position to -200, it will automatically go to -14 on start, so that would be a solution. But i rather want to find out how -14 and 14 relate to the height 128, and set the start position of the content dynamically according the the height. But setting the anchoredPosition to negative number way lower seems to work
    Code (CSharp):
    1. containerRectTransform.anchoredPosition = new Vector2(0, -200);
     
  7. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    As you know, the position of a RectTransform is its pivot relative to the anchor. You said your content is 128 high, and that the position is -14 / 14 when at the top / bottom, so I'm guessing that your view rect is 100 high and that both your pivot and anchor is in the middle.

    This means that when the position is 0, the content is 14 too big in both directions (up and down). By moving it 14 down, the content bottom will match with the view bottom, and by moving it 14 up the content top with match with the view top.

    However, you shouldn't need to do any of this math at all. If you want the content to start being at the top, simply set both pivot and anchor to the top and then set the position to 0. Similar thing if you want it at the bottom.
     
    Vedmate likes this.
  8. hosseinAmini

    hosseinAmini

    Joined:
    Jun 23, 2015
    Posts:
    1
    i had same problem. with set scrollbar's value to 1 it fixed
     
  9. jhuck

    jhuck

    Joined:
    Apr 7, 2016
    Posts:
    1
    I think you've forgot the Suffix (f)
    So write bar.value = 1f;
    And I think then it works.
     
  10. Meteora

    Meteora

    Joined:
    Jul 3, 2013
    Posts:
    1
    I had a similar issue, and after an hour of fiddling with it, this enlightened me and I fixed the issue.
    Thank you!
     
  11. Griffo

    Griffo

    Joined:
    Jul 5, 2011
    Posts:
    700
    This is old, but it's been doing my head in for hours, and just a 'yield return null;' done the trick ..
     
  12. Absurd-Studios

    Absurd-Studios

    Joined:
    Jul 21, 2019
    Posts:
    4
    I just wanted to say thank you for this. Fixed my problem and was definitely the easiest solution for me. I knew that I could've fixed it with timing (as stated by lilymontoute - good solution) , but I felt there had to be an easier solution than starting an entire coroutine and suspending functionality until a certain point (which in my case could've been indefinite depending on how users go about using the app). Thank you for the answer that's still coming in clutch ~6 years down the road
     
  13. florinel2102

    florinel2102

    Joined:
    May 21, 2019
    Posts:
    76
    For me worked
    Code (CSharp):
    1.      private void OnEnable()
    2.     {
    3.         StartCoroutine(SetValueScrollBar());
    4.     }
    5.  
    6.    IEnumerator SetValueScrollBar()
    7.     {
    8.         yield return null;
    9.  
    10.         yield return null;
    11.  
    12.         scrollbar.value = 0f;
    13.     }
     
    PZ4_Bailey and cocuma22 like this.
  14. Lokesh2022

    Lokesh2022

    Joined:
    May 8, 2021
    Posts:
    9
    nice, it worked. thank you
    along with, add this to the level load button, to save the last position of the scroll position

    public float scrollValue;

    Scrollbar bar;

    public IEnumerator Start()
    {
    Debug.Log("Now its called");
    yield return null; // Waiting just one frame is probably good enough, yield return null does that
    bar = GetComponentInChildren<Scrollbar>();
    bar.value = scrollValue;

    // Debug.Log(bar.value);


    LoadScroll();
    Debug.Log("Now its setted");

    }

    // add save scroll function to the onclickevent button
    public void SaveScroll()
    {
    PlayerPrefs.SetFloat("ScrollKey", bar.value);
    Debug.Log("Saved");
    PlayerPrefs.Save();
    }

    public void LoadScroll()
    {
    bar.value = PlayerPrefs.GetFloat("ScrollKey");
    }

    public void DeletePrefabData()
    {
    PlayerPrefs.DeleteAll();
    SceneManager.LoadScene(0);
    }