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

How to position ScrollRect to another item?

Discussion in 'UGUI & TextMesh Pro' started by LastGecko, Sep 16, 2014.

  1. LastGecko

    LastGecko

    Joined:
    Sep 16, 2014
    Posts:
    2
    I'm trying the 4.6 beta and I have a masked ScrollRect with buttons inside. Since I prefer using Gamepad I noticed that for some reason the ScrollRect fails to jump to the currently selected object. The same happens when using keyboard. So I guess we need to do it manually and I was hoping there would be a ScrollRect.CenterOn(GameObject item) function, but there isn't. I know about ScrollRect.verticalNormalizedPosition and ScrollRect.horizontalNormalizedPosition but I'm unsure how I can take my objects position to get a usable value out of to assign it. Ideally, the selected object would be in the perfect center of the ScrollRect. A long time ago I used NGUI and it supported that, but I can't figure it out with uGUI. Does anyone know how to do it?

    Many thanks in advance!
     
  2. davebuchhofer

    davebuchhofer

    Joined:
    Nov 9, 2007
    Posts:
    126
    Try setting the normalize position to where it would reveal the transform
    Code (csharp):
    1.  
    2.     public ScrollRect scroll;
    3.  
    4.     void ShowInTabControl(){
    5.         float normalizePosition = (float)transform.GetSiblingIndex() / (float)scroll.content.transform.childCount;
    6.         scroll.verticalNormalizedPosition = 1-normalizePosition;
    7.     }
    8.  
     
  3. davebuchhofer

    davebuchhofer

    Joined:
    Nov 9, 2007
    Posts:
    126
    That wont center it exactly.. you'll need to know how many items are possible to be visible at once and do a little shifting/math on your normalizePosition to do that.
     
  4. LastGecko

    LastGecko

    Joined:
    Sep 16, 2014
    Posts:
    2
    Thanks dave, I got it working. Your code didn't work by itself until I did some trial and error with it. Here is what I ended up using. I'm sure it's quiet terrible, but it seems to work for me (it doesn't really center anything but it moves the position good enough)

    I use this script on the ScrollRect
    Code (csharp):
    1.  
    2.   private ScrollRect scroll;
    3.   private RectTransform scrollTransform;
    4.  
    5.   void Start()
    6.   {
    7.   scroll = GetComponent<ScrollRect>();
    8.   scrollTransform = GetComponent<RectTransform>();
    9.   }
    10.  
    11.   public void CenterToItem(RectTransform obj)
    12.   {
    13.   float normalizePosition = scrollTransform.anchorMin.y - obj.anchoredPosition.y;
    14.   normalizePosition += (float)obj.transform.GetSiblingIndex() / (float)scroll.content.transform.childCount;
    15.   normalizePosition /= 1000f;
    16.   normalizePosition = Mathf.Clamp01(1 - normalizePosition);
    17.   scroll.verticalNormalizedPosition = normalizePosition;
    18.   Debug.Log(normalizePosition);
    19.   }
    20.  
    I call the function from another script on my button that has the event interface implemented. Because my button is a child of another object I pass the parents RectTransform to it since for some reason only that appears to store the proper position that I needed. The call on my button is made like so:
    Code (csharp):
    1.  
    2.   public void OnSelect(BaseEventData eventData)
    3.   {
    4.   if (scrollCenterScript != null)
    5.   scrollCenterScript.CenterToItem(rTransform.parent.GetComponent<RectTransform>());
    6.   }
    7.  
    Thank you for the help. Of course improvements are always welcome if anyone has them :)
     
    Last edited: Sep 16, 2014
  5. kujo

    kujo

    Joined:
    Aug 19, 2013
    Posts:
    106
    Hi,

    Thanks for this script, its given me a good start, but I'm having a little problem in centering my item, it ends up being further and further out as I step through my items. I'm using this technique as a level select along a map. (Think Super Mario). I want to centre the scrollrect on one of my levels, but they aren't equally spaced out, so I'm not sure this:

    Code (csharp):
    1.  
    2. normalizePosition +=(float)obj.transform.GetSiblingIndex()/(float)scroll.content.transform.childCount;
    3.  
    Will do what I need. Is there a way to modify this script so that I can centre on any item, regardless of the even spacing?

    Thanks
     
  6. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    [Edit]

    Sorry, centering is broken for big lists, fixing it right now. Back soon!
     
    Last edited: Nov 17, 2014
  7. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    Ok, now it is fixed. There seems to be a bit of an offset error. Can seem to find it now but (for me) it not an issue right now.

    -----------------

    Hi,
    I am working on this very same thing. I have made a script that moves the scroll rect content so that an item is shown centered. It uses the target item, content and mask RectTransforms so it ignores child count and child hierarchy, meaning you can center on a child of a child of a child of content and the position "should" be correct.

    I am not very good at math so this script posibly look like trash to someone that knows, but it is my trash and my love for it is unconditional... until Unity implement this by themselves :D.

    Important thing, in my script, I am assuming that content childs have their pivot point placed up-left. Results my vary if different. Also I am using GoKit for animations, if you are not I have left commented a direct assignment of the new position so you can uncomment it and comment the GoTo animation.
    Code (csharp):
    1.  
    2. //_sr.normalizedPosition = normalizedPosition;
    3.   Go.to(_sr, AnimTime, new GoTweenConfig().vector2Prop("normalizedPosition", normalizedPosition));
    4.  
    http://pastebin.com/FecBh4mh

    1. Add the script to a scroll rect
    2. Assign the mask RectTransform used to calculate the visible area. It can be a different object. It will use it to know which position is the center.
    3. Configure properties as needed :)
    4. Call CenterOnItem(RectTransform target) to center the scroll rect in a certain item

    If you find a bug or have a better implementation please let me know.
     
    Animus_123 likes this.
  8. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    I have fixed a small bug that caused bad centering when the target item was deep in the content hierarchy.
    Updated script:

    http://pastebin.com/EgU1Us9L
     
  9. kujo

    kujo

    Joined:
    Aug 19, 2013
    Posts:
    106
    Hi John,

    Thank you for sharing your code. I'll have a go with you (newly) modified version and let you know how it goes :)
     
  10. kujo

    kujo

    Joined:
    Aug 19, 2013
    Posts:
    106
    Hi John,

    Just tried this out, and unfortunately it doesn't work out for me. I always end up near the end of the scroll rect. With the item I'm choosing, I should be close to the centre. Any idea what I might be doing wrong?
     
  11. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    Well thats bad, sorry. I have tested the script in both directions and with different content structures and thought it worked quite well. I'm sure at somepoint I messed up with the anchors and alignments and whatnot :p

    Ok, let's get to it. I have little info about your problem so excuse me for the interrogation:

    - Do you have an empty project with the same problem? (so I can directly test the error)
    - Are you using a mask?
    - Is it a mask?
    - Is it a child (at any depth) of the scrollrect object and a parent (at any depth) of the content object
    - At wich depth is the item you want to center?
    - Is it a direct child of content?
    - Is it deep into the content hierarchy?
    - What is the content anchor position?
    - What is the item anchor position?

    Thanks!
     
  12. kujo

    kujo

    Joined:
    Aug 19, 2013
    Posts:
    106
    Hi,

    Started writing some detail to this before, but the forum stopped working for me...

    Anyway:

    - No, but I can possibly create one
    - I have a RectTransform that is set to the size of the canvas (which is in world space and is the size of the screen) that I've allocated to the Mask variable
    - Doesn't seem to make any difference if it has the mask component on it or not
    - I've attached a screenshot of my hierarchy, I'm after centring on any of the Level_{0}_{1} game objects, so not very deep.
    - The Level game objects have their anchors top left (as you required)
    - Their positions will vary depending where they are on the map. I've attached another screenshot of what the map looks like. There is a 3D environment that will be visible as well (which is in the Environment gameobject in the hierarchy)

    Capture.PNG

    63551929853.png
     
  13. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    Well, I did not test it in world space, the script was thought for 2D scrolling. I will test it with a simple example. I am using the mask to calculate an offset from the screen center, but with your setup the mask tweak does not work since the mask and the content are not on the same plane.

    I really like your idea for a map :). By the way, the pivot alignment should only cause a different offset and only in a very small amount so you can test different alignments if you want to.

    2 questions:

    - What is the dragable object?
    - Why is the mask inside the content? <- this is curiosity.

    All the examples I have tested where like this:
    ScrollRectStructure.png
     
  14. kujo

    kujo

    Joined:
    Aug 19, 2013
    Posts:
    106
    The Dragable object is there so there is a transparent image all the way along for the raycasting to hit, so it can fully scroll. I found otherwise, I had to click on one of the level numbers instead.

    Mask is there because I didn't know where else to put it. I'll set up my scene hierarchy like your as see if that fixes things for me.
     
  15. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    I did not understand you when we talked about your map. The script I posted is intended for 2D maps, mostly because I did not think of a 3D map when doing it.

    This script does not work with this kind of scrollrect. I am doing a few tests to see if I can get something working in 3D.
     
  16. kujo

    kujo

    Joined:
    Aug 19, 2013
    Posts:
    106
    ahh, I see. I was assuming the same thing would work, as the items are still in a scroll rect, but the position it chooses for each of them is way off. E.g. looking at my picture above, I'm trying to centre on Level 4, but it ends up beyond the end of the content.
     
  17. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    Well, I use a lot of screen position jumbo mambo to calculate the scroll rect displacement so it does not work very well with 3D scroll rects.

    But since I was interested I made a little project to toy a bit with this and ended up with something funny:
    1. Take an item position in the screen
    2. Calculate the direction in the screen for that item to reach the center of the screen
    3. Adjust the scroll rect horizontal and vertical position in that direction
    4. Repeat until target item is whithin a threshold from the center of the screen
    5. It work
    6. Laugh like a maniac! MWAHAHAHAhahahahahahaha
    It is not a very professional work and the code is a bit ugly but since it works and I think it does something similar to what you want, there is no harm it checking it :)
    https://drive.google.com/file/d/0B2e1MCu4wYC2cUJvcXVuMmNWQ28/view?usp=sharing

    See how it goes. Notes:
    • It centers onto the target pivot point
    • No need for mask
    • Scrollbars are there for me to manually moveit and test it, can be deleted
    • Drag does not work, I did not need it, I had the scroll bars :p
    Good luck
     
    Chuvi likes this.
  18. kujo

    kujo

    Joined:
    Aug 19, 2013
    Posts:
    106
    Fantastic! works perfectly, even with drag!

    Thank you so much for the help!
     
  19. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    Just a lucky shoot, glad it worked for you. There is a lot to improve in that script so have fun :p
     
  20. kujo

    kujo

    Joined:
    Aug 19, 2013
    Posts:
    106
    yeah, it needs a little tweaking, but fundamentally its sound. I get a little jerky bit as it approaches the item which I can fix. Thanks again
     
  21. kujo

    kujo

    Joined:
    Aug 19, 2013
    Posts:
    106
    I'm curious - is it possible to do this without the tweening? so that on start up it'll just be centred on an item?
     
  22. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    Actually I think you can but did not try it. You should be able to do the same in a normal function (not a coroutine) so it is done in a single frame. Just an idea.

    To avoid the jerkiness try to increase the precision variable or better yet, if at a frame the target.x is greated than the screenCenter.x and the next frame is less than it, then you already reached the x position and are dancing around it.
     
  23. kujo

    kujo

    Joined:
    Aug 19, 2013
    Posts:
    106
    Hi John,

    I tried your idea of a normal function before I asked the question, unfortunately it didn't work. I think the reason for it is is because the camera never updates, and so the targetPosition variable is always the same, and so then is the yDifference (I'm only using vertical scroll), and so never terminates.
     
  24. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    Well then it seems the UI needs a frame to recalculate and since we are "using" the scroll rect and letting it do all the work our hands are tied on this issue.

    There are maybe 2 things that can be done:
    1. Discard this method and actually build something that does not rely on the actual scroll rect to calculate the new position.
    2. Use a variable speed, when the distance between the target screen position and the center position is greater than X, increase the speed at which it moves and decrease it slowly as you approach your target position.

    Obviously the method 1 is the best while the method2 is the dirty patch.

    If you go for number 1, currently I don't have time to test it but you could try:
    1. Putting a collider/trigger at your environment object/s. It should cover all of it. This can be invisible and has to be on the same level (height) as the UI widgets you are using.
    2. When you click your target: store your UI target world position.
    3. Raycast from the screen center until you collide with the collider from point 1. You have the point in that plane that is right at the screen center.
    4. Store that point.
    5. That point - original target point = displacement in world space (only X and Z axes since the points are at the same height).
    6. With that displacement, you can move your content instantly or tweening or whatever you want to do.
    7. This way you don't even need an scrollrect, content mask or anything else.
    This solution is a lot more elegant and professional and you have the control over every step without relaying on the UI for the movements and/or calculations.
     
  25. kujo

    kujo

    Joined:
    Aug 19, 2013
    Posts:
    106
    Thanks again for you help. I'll have a play around and let you know what I find :)
     
  26. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Hi @-JohnMore- , ive been testing your script and it seems great so far, but I have an issue. I am using it to do a bit of trickery, and I am using the Mask to specify an area I want the object to be centred in (I need the object to be centred on the right half of the screen, so I have setup the mask using its anchors to fill only that portion). When I do this, it correctly centres it within the bounds of the masked area, but not in the correct position. It seems to be taking it from the left side of the screen, not from the masks actual position. How would I go about changing it so its takes into account the actual Mask position?
     
  27. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    So you mean that you have an scroll rect with a size of x,y but the mask is smaller and it is located on the right half of the screen, am I right?

    My fault, even if it was not my initial intention somewhere during the tests I assumed the mask had always the same position and size of the scrollrect. Let me check it...
     
  28. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Thats correct. My scroll rect is pretty much full screen size, but the mask only covers the right 40% of the scroll rect. It works, and finds the position correctly, but its assuming its on the left side of the screen.
     
  29. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    Now I feel dumb :/

    The other day I did some tests for a 3D scroll for @kujo and after using the same approach the function to center the item is now 5 lines length. And that is being verbose :)

    In my tests it centers it in the mask wherever it is and whatever it's size or shape. Having some issues with really deep hierarchies. Working on it now.

    It's small so I'll paste it here:

    Code (csharp):
    1.  
    2. #region USING
    3.  
    4. using UnityEngine;
    5. using UnityEngine.UI;
    6.  
    7. #endregion
    8.  
    9. [RequireComponent(typeof (ScrollRect))]
    10. public class ScrollRectEnsureVisible : MonoBehaviour
    11. {
    12.   public float AnimTime = 0.15f;
    13.   public bool Log = true;
    14.   public RectTransform MaskTransform;
    15.  
    16.   private ScrollRect _sr;
    17.   Transform _scrollT;
    18.   private RectTransform _content;
    19.  
    20.   private void Awake()
    21.   {
    22.   _sr = GetComponent<ScrollRect>();
    23.   _scrollT = _sr.transform;
    24.   _content = _sr.content;
    25.   }
    26.  
    27.   public void CenterOnItem(RectTransform target)
    28.   {
    29.   //the item is here
    30.   var itemAnchorPositionInScroll = _scrollT.InverseTransformPoint(target.position);
    31.   //but must be here
    32.   var targetAnchorPositionInScroll = _scrollT.InverseTransformPoint(MaskTransform.TransformPoint(Vector2.zero));
    33.   //so it has to move this distance
    34.   var difference = targetAnchorPositionInScroll - itemAnchorPositionInScroll;
    35.   difference.z = 0f;
    36.   //we move the content to align the item at the correct position
    37.   var newAnchoredPosition = _content.parent.InverseTransformPoint(_content.position + difference);
    38.   _content.anchoredPosition = newAnchoredPosition;
    39.   //also can tween the movement
    40.   //Go.to(_content, AnimTime, new GoTweenConfig().vector2Prop("anchoredPosition", newAnchoredPosition));
    41.   }
    42. }
    43.  
     
    Last edited: Nov 21, 2014
  30. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Hmm, still not working for me. Its giving some very odd behaviour now, the previous version seemed to be closer than this one.

    Here are a couple of screenshots. I am centering the top left crown icon. The first shows the icon in relation to before I center it, and the second shows after I center it. As you can see, it does not really get close.
    Screen Shot 2014-11-21 at 11.56.43.png
    Screen Shot 2014-11-21 at 11.56.58.png
    Here is another screenshot showing my hierarchy, incase that helps. Ive highlighted the item I am going to center, the mask, and the scrollrect.
    Screen Shot 2014-11-21 at 12.00.47.png
     
  31. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Ok, it is working (nearly), but just giving funny results for the first few because they are within the starting section of the scroll rect, so its springing back :)

    Ill do some more testing and see if I have any other issues. The only issue now is that its not centering exactly within the Mask for me, kind of offset to the left for some reason. But its nearly there!
     
  32. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    I'm going to replicate that structure and try again. By the way, there was a bug:
    Code (csharp):
    1.  
    2.   var difference = targetAnchorPositionInScroll - itemAnchorPositionInScroll;
    3.  
    has to be
    Code (csharp):
    1.  
    2.   var difference = targetAnchorPositionInScroll - itemAnchorPositionInScroll;
    3.   difference.z = 0f;
    4. [CODE]
    5.  
    6. So the different z position is not used since we are working on 2D.
     
  33. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
  34. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Sure, ill give it a go now.
     
  35. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    So, that works great for me! But, when I modify the sample to replicate how I have mine setup, the issues start occuring again. Attached is the package for you to test. What I have changed:
    • CanvasScaler is set to "Scale With Screen Size", set to iPad resolution (1024x768) and set to match height
    • ScrollRect "Content" is set to a fixed size (which will enclose our content perfectly).
    • Container - Buttons is stretched to be the full size of the ScrollRect "Content"
    • All buttons are anchored to the top left of their parent to help us with positioning.
    Thanks for the help, hopefully you can figure out the issue :)
     

    Attached Files:

  36. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Ok, I have figured it out. Seems to be working fine for me now. Here is the code:
    I am using DOTween as my tweening engine, just comment that stuff out if you are using something else, and add in your own.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using DG.Tweening;
    4.  
    5. [RequireComponent(typeof(ScrollRect))]
    6. public class ScrollRectEnsureVisible : MonoBehaviour
    7. {
    8.  
    9.     #region Public Variables
    10.  
    11.     public float _AnimTime = 0.15f;
    12.     public bool _Snap = false;
    13.     public bool _LockX = false;
    14.     public bool _LockY = true;
    15.     public RectTransform _MaskTransform;
    16.  
    17.     #endregion
    18.  
    19.     #region Private Variables
    20.  
    21.     private ScrollRect mScrollRect;
    22.     private Transform mScrollTransform;
    23.     private RectTransform mContent;
    24.  
    25.     #endregion
    26.  
    27.     #region Unity Methods
    28.  
    29.     private void Awake ()
    30.     {
    31.         mScrollRect = GetComponent<ScrollRect> ();
    32.         mScrollTransform = mScrollRect.transform;
    33.         mContent = mScrollRect.content;
    34.     }
    35.  
    36.     #endregion
    37.  
    38.     #region Public Methods
    39.  
    40.     public void CenterOnItem (RectTransform target)
    41.     {
    42.         Vector3 maskCenterPos = _MaskTransform.position + (Vector3)_MaskTransform.rect.center;
    43.         Debug.Log ("Mask Center Pos: " + maskCenterPos);
    44.         Vector3 itemCenterPos = target.position;
    45.         Debug.Log ("Item Center Pos: " + itemCenterPos);
    46.         Vector3 difference = maskCenterPos - itemCenterPos;
    47.         difference.z = 0;
    48.  
    49.         Vector3 newPos = mContent.position + difference;
    50.         if (_LockX) {
    51.             newPos.x = mContent.position.x;
    52.         }
    53.         if (_LockY) {
    54.             newPos.y = mContent.position.y;
    55.         }
    56.  
    57.         if (_Snap) {
    58.             mContent.position = newPos;
    59.         } else {
    60.             DOTween.To (() => mContent.position, x => mContent.position = x, newPos, _AnimTime);
    61.         }
    62.     }
    63.  
    64.     #endregion
    65. }
     
    AllanRW likes this.
  37. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    I am glad you got it. I just did too :)

    The spring effect is because you don't have enough space at the left of your first button, so the content springs back (scrollrect configured as elastic).

    There were some other bugs in my version, I have now included the pivot point when calculating an object's position so it should work no matter the alignment of the object.

    Also, I can see you have included some code to lock some axis. I have done the same but using the scrollrect configuration.

    I will leave it here, maybe someone wants to take a look at it.
     

    Attached Files:

  38. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Thanks! I will check yours out as well, might be a better implementation. Ill use whatever works :)
     
  39. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    Thanks. I am still working on it. This version centers the objects much exactly but it has problems with elastic and clamp movement types. Elastic just springs back while clamp get stuck until you manually move it. I am going to try and use the normalizedPosition from scrollRect so no matter the movement type, the target position stays within the scrollrect bounds.
     
  40. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Yeah sounds good. There are some issues, which I will have to hack around at the moment, but for the most part its working ok.
     
  41. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    I wrote a new version. It's the same until you get the difference. Then I translate it to content displacement percentage base on the content size and the scrollrect size which gives me a nice % ratio of displacement. Then you just have to apply some clamping if the movement type is not unrestricted and now you can reposition the content through the scrollrect, respecting its settings. I have tested it in my scrollrects and it's looking good.

    After the difference is calculated I did this:
    Code (csharp):
    1.  
    2.   var normalizedDifference = new Vector2(
    3.   difference.x / (_mContent.rect.size.x - _mScrollTransform.rect.size.x),
    4.   difference.y / (_mContent.rect.size.y - _mScrollTransform.rect.size.y));
    5.  
    6.   Debug.Log("Normalized difference: " + normalizedDifference);
    7.  
    8.   var newNormalizedPosition = _mScrollRect.normalizedPosition - normalizedDifference;
    9.   Debug.Log("New normalized position: " + newNormalizedPosition);
    10.   if (_mScrollRect.movementType != ScrollRect.MovementType.Unrestricted)
    11.   {
    12.     newNormalizedPosition.x = Mathf.Clamp01(newNormalizedPosition.x);
    13.     newNormalizedPosition.y = Mathf.Clamp01(newNormalizedPosition.y);
    14.     Debug.Log("Clamped normalized position: " + newNormalizedPosition);
    15.   }
    16.  
    17.   if (Snap)
    18.   {
    19.     _mScrollRect.normalizedPosition = newNormalizedPosition;
    20.   }
    21.   else
    22.   {
    23.     Go.to(_mScrollRect, AnimTime, new GoTweenConfig().vector2Prop("normalizedPosition", newNormalizedPosition));
    24.   }
    25.  
    26.  
     

    Attached Files:

  42. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Thanks. Ill check it out when I get a chance :)
     
  43. redthrawn

    redthrawn

    Joined:
    May 8, 2013
    Posts:
    27
    Just a heads up: NicerOutline.cs gives me an AOT cross-compile error when I try to build for iOS.
     
  44. mr-sambarlow

    mr-sambarlow

    Joined:
    Nov 11, 2014
    Posts:
    36
    Same here. Any fix for this?
     
  45. Lan14n

    Lan14n

    Joined:
    Feb 8, 2014
    Posts:
    4
    If anyone is interested here's edge scrolling instead of center scrolling. Currently only works vertically.



    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using UnityEngine.EventSystems;
    4.  
    5. [RequireComponent( typeof( ScrollRect ) )]
    6. public class ScrollToSelected : MonoBehaviour {
    7.  
    8.     public float scrollSpeed = 10f;
    9.  
    10.     ScrollRect m_ScrollRect;
    11.     RectTransform m_RectTransform;
    12.     RectTransform m_ContentRectTransform;
    13.     RectTransform m_SelectedRectTransform;
    14.        
    15.     void Awake() {
    16.         m_ScrollRect = GetComponent<ScrollRect>();
    17.         m_RectTransform = GetComponent<RectTransform>();
    18.         m_ContentRectTransform = m_ScrollRect.content;
    19.     }
    20.  
    21.     void Update() {
    22.         UpdateScrollToSelected();
    23.     }
    24.  
    25.     void UpdateScrollToSelected() {
    26.  
    27.         // grab the current selected from the eventsystem
    28.         GameObject selected = EventSystem.current.currentSelectedGameObject;
    29.  
    30.         if ( selected == null ) {
    31.             return;
    32.         }
    33.         if ( selected.transform.parent != m_ContentRectTransform.transform ) {
    34.             return;
    35.         }
    36.  
    37.         m_SelectedRectTransform = selected.GetComponent<RectTransform>();
    38.  
    39.         // math stuff
    40.         Vector3 selectedDifference = m_RectTransform.localPosition - m_SelectedRectTransform.localPosition;
    41.         float contentHeightDifference = ( m_ContentRectTransform.rect.height - m_RectTransform.rect.height );
    42.                
    43.         float selectedPosition = ( m_ContentRectTransform.rect.height - selectedDifference.y );
    44.         float currentScrollRectPosition = m_ScrollRect.normalizedPosition.y * contentHeightDifference;
    45.         float above = currentScrollRectPosition - ( m_SelectedRectTransform.rect.height / 2 ) + m_RectTransform.rect.height;
    46.         float below = currentScrollRectPosition + ( m_SelectedRectTransform.rect.height / 2 );
    47.        
    48.         // check if selected is out of bounds
    49.         if ( selectedPosition > above ) {
    50.             float step = selectedPosition - above;
    51.             float newY = currentScrollRectPosition + step;
    52.             float newNormalizedY = newY / contentHeightDifference;
    53.             m_ScrollRect.normalizedPosition = Vector2.Lerp( m_ScrollRect.normalizedPosition, new Vector2( 0, newNormalizedY ), scrollSpeed * Time.deltaTime );
    54.         } else if ( selectedPosition < below ) {
    55.             float step = selectedPosition - below;
    56.             float newY = currentScrollRectPosition + step;
    57.             float newNormalizedY = newY / contentHeightDifference;
    58.             m_ScrollRect.normalizedPosition = Vector2.Lerp( m_ScrollRect.normalizedPosition, new Vector2( 0, newNormalizedY ), scrollSpeed * Time.deltaTime );
    59.         }
    60.  
    61.     }
    62.  
    63. }
     
    Sarai, MollySpryFox, Oskiii and 4 others like this.
  46. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Try and get this added into the useful uGUI scripts thread on here, im sure more people would love to use this.
     
    erebel55 likes this.
  47. pioj

    pioj

    Joined:
    Nov 5, 2012
    Posts:
    34
    Lan14n, I can't get your script working correctly. It looks like as it depends a lot of the size of the content and its margins. I also can't add a panel at the bottom, for an item description, like in SOTN... Check this gif:



    There are 7 items inside this grid, but only scrolls up to the 5th. Only the 6th is asumed to be partially blocked by the panel_description...
     
  48. pioj

    pioj

    Joined:
    Nov 5, 2012
    Posts:
    34
  49. AverageProg

    AverageProg

    Joined:
    Jun 25, 2015
    Posts:
    38
    Guys, if you spent 10 minutes thinking about it you would have found the solution to your problem

    instead of writing that horrifying mess I see up there

    I am not going to make this code work in all case scenarios but here is the pseudocode. (working for me)

    I am deliberately not posting the whole code because I want you to use your brain a little.
    (notice this doesn't center the items in the middle but brings them on top)

    Assuming scroll rect items have pivot on Top and expand downwards

    float scrollPercentage = itempos / (containerHeight - panelHeight);
    float normalizedPosition = 1 - scrollPercentage - (scrollPercentage / containerHeight);

    I am not going to expand functionality further as I already achieved what I wanted.

    Yes I am an asshole <.<

    P.s. not so asshole as you might think, if you need assistance to understand what I wrote up there just reply in here, if i ever read it again i will try to assist, now back to work :)
     
    Last edited: Jun 25, 2015
  50. ImitationCrab

    ImitationCrab

    Joined:
    Jul 1, 2015
    Posts:
    1
    Do you mind explaining further what you did? I have been trying to solve this for a few hours but have not been able to. There must be something I am missing but I have no idea what.

    Assuming you are using Lan14n's code, the itemposition would be the currentSelectedGameObject, the container height would be from m_ContentRectTransform.rect.height, and panelHeight is from.. m_RectTransform? How are you incorporating that normalizedPosition value into the code? Are you doing that instead of what is contained in the "> above" and "< below" conditionals?
     
    afftar likes this.