Unity UI- Scroll Rect (Loop buttons)

In new UI system, I use scroll Rect property to create the scrolling buttons. But how do I make the scrolling loopable? In the movement type, I fine options for Elastic, Rigid and Unrestricted. Any clue? Would be appreciated. Thanks.

You can use the normalized position of your scroll rect and decide that when reaching 0.1f you fetch the bottom item

getting the one with the higher value and place up top:

then do the opposite when you get to 0.9f.

Obviously 0.1 and 0.9 should be tweak to your needs but maybe that could be a start.

EDIT:

here is a basic working example.

you would have the following hierarchy:

-Canvas
    - PanelA with Scroll rect component and InifiniteScroll component
          - PanelB to be used as Scroll Rect, with HorizontalLayoutGroup component
                  - Button
                  - Button
                 ...

public class InfiniteScroll : MonoBehaviour {
	public ScrollRect scroll;        //  Drag PanelB
	public Transform leftCursor, rightCursor;  // Add empty game object to your scene to define the breakpoint
    // Actually this could be using the screen dimension but I was just doing it quick
    // the x values of those two objects will define when to snap

	private int count = 0;
	private float size = 0f;
    private Transform panelTr = null;
	void Start()
	{
		count = panelTr.childCount - 1; // How many kids do we have?
		size = GetButtonSize();   // Here you pass the width of a button
	}
	public void  Movement()
	{
		Transform left = panelTr.GetChild (0);            // Get first kid
		Transform right = panelTr.GetChild(count);    // Get last kid
		if(left.position.x > leftCursor.position.x)         // is the first over the limit
		{
			RectTransform rt = panelTr as RectTransform;     
			Vector2 v = rt.anchoredPosition;           
			v.x -= size;
			rt.anchoredPosition = v;                       // Those 4 lines will move the scroll rect to the left by the size of a button
			right.SetAsFirstSibling();                      // put last as first, then it looks like nothing moved
		}
		else if(right.position.x < rightCursor.position.x)
		{
			left.SetAsLastSibling();
			RectTransform rt = panelTr as RectTransform;
			Vector2 v = rt.anchoredPosition;
			v.x += size;
			rt.anchoredPosition = v;
		}
	}
}

this is not yet perfect, you will see that if scrolling fast, it may get a little messy. On the other hand scrolling slow works fine for me.
I would leave it to you now and invite everyone to modify that code until it is working great.

The Movement method needs to be added as a listener to the ScrollRect event system.

I have found a solution which might not be effective, but it works good. Since I need the buttons to scroll through my game object which is Augmented Object it is difficult with the current Unity UI system, at least to me.

So, I found the other way around. Create a empty Game Object and add MenuScroll Script to it. Create a game object( or the object that you want it to be in center) and add it in the MenuScroll Script using inspector. Create number of buttons (according to your need), I used Sprite as a button. It totally depends on you, You can create simple cube, whatever you create it will be treated as buttons, Simply add the MenuScrollButton script to it (Ensure you add it to all the buttons).

public class CirclePosition
{
	public CirclePosition()
	{
		Angle = 0f;
		CircleCenter = Vector3.zero;
		CircleSize = 0f;
	}

	public float Angle
	{
		get;set;
	}
	
	public Vector3 CircleCenter
	{
		get;set;
	}

	public float CircleSize
	{
		get;set;
	}
}

MenuScroll Script

{

	public GameObject Center;
	public float CircleSize = 2f;
	public float ScrollSlowDownFactor = 100f;

	private MenuScrollButton[] buttons;
	private CirclePosition position;

	private bool drag = false;
	private float lastMousePosition = 0f;
	private float swipe = 0f;

	void Awake()
	{
		if(Center == null)
			Center = this.gameObject;

		position = new CirclePosition();
		buttons = gameObject.GetComponentsInChildren<MenuScrollButton>();
		SetCirclePosition();

		for(int i = 0; i < buttons.Length; i++)
			CalcAngleOffSet(i);
		SetPositions();
	}

	private void SetCirclePosition()
	{
		position.CircleCenter = gameObject.transform.position;
		position.CircleSize = CircleSize;
	}

	private void CalcAngleOffSet(int i)
	{
		float angle = (2f / buttons.Length) * i * Mathf.PI;
		buttons*.SetOffSet(angle);*
  • }*

  • void Update()*

  • {*

  •  if(Input.GetMouseButtonDown(0))*
    
  •  {*
    
  •  	lastMousePosition = Input.mousePosition.x;*
    
  •  	drag = true;*
    
  •  }*
    
  •  if(Input.GetMouseButtonUp(0))*
    
  •  	drag = false;*
    
  •  if(drag)*
    
  •  	Swipe();*
    
  • }*

  • void Swipe()*

  • {*

  •  swipe = lastMousePosition - Input.mousePosition.x;*
    
  •  SetPositions();*
    
  • }*

  • private void SetPositions()*

  • {*
    _ position.Angle += swipe * Time.deltaTime / ScrollSlowDownFactor;_

  •  foreach(var b in buttons)*
    
  •  b.SetPosition(position);*
    
  • }*
    }
    MenuScroll Button
    {

  • public UnityEvent OnClick;*

  • private float angleOffset = 0f;*

  • public void SetOffSet(float offset)*

  • {*

  •   angleOffset = offset;*
    
  • }*

  • public void SetPosition(CirclePosition position)*

  • {*

  •   gameObject.transform.localPosition =* 
    

_ new Vector3 ((Mathf.Sin(position.Angle + angleOffset) * position.CircleSize),_

  •   	             0f,*
    

((Mathf.Cos(position.Angle + angleOffset) * position.CircleSize)));

  • }*
  • public void OnMouseDown()*
  • {*
  •   OnClick.Invoke();*
    
  • }*
    }