1
votes

I work on a simple scrollable UI in Unity.

  • I have a canvas in the scene, it has Empty as a child.
  • The Empty is a parent for a long UI panel with different buttons.

I use the following script (assigned to the Empty) to make it scrollable:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class PageSwiper : MonoBehaviour, IDragHandler, IEndDragHandler
{
    private Vector3 scrollableUILocation;



    // Start is called before the first frame update
    void Start()
    {
        scrollableUILocation = transform.position;
    }
    public void OnDrag(PointerEventData data)
    {
        float difference = data.pressPosition.x - data.position.x;
        transform.position = scrollableUILocation - new Vector3(difference, 0, 0);
    }
    public void OnEndDrag(PointerEventData data)
    {
        scrollableUILocation = transform.position;

    } 
}

The problem is that I can scroll the UI panel outside of the screen. So I need to make it impossible, or make it so that if I scroll it too far, it smoothly returns back (to the end or to the start of the UI panel, depending on which is closer)

How can I do it?


I tried to implement the following solution but it doesn't work:

I added two Empty object on the left and on the right from the UI panel. I tried to make my UI panel to smoothly move at the position of one of those empty objects in case if I would move it close enough to them. But it doesn't work.

 public void OnEndDrag(PointerEventData data)
{
    if (Vector3.Distance(transform.position, StartPoint.transform.position) < 1.0f)
    {
        StartCoroutine(SmoothMove(transform.position, StartPoint.transform.position, easing));
    }

    else if (Vector3.Distance(transform.position, EndPoint.transform.position) < 1.0f)
    {
        StartCoroutine(SmoothMove(transform.position, EndPoint.transform.position, easing));
    }


}

IEnumerator SmoothMove(Vector3 startpos, Vector3 endpos, float seconds)
{
    float t = 0f;
    while (t <= 1.0)
    {
        t += Time.deltaTime / seconds;
        transform.position = Vector3.Lerp(startpos, endpos, Mathf.SmoothStep(0f, 1f, t));
        yield return null;
    }
}
2
your OnEndDrag - both conditions dnd routine parameters seem to be identical - BugFinder
@BugFinder Thank you, fixed it. I was testing with only one "if" statement, forgot to change variable names when added second statement for this question. - Rumata
Do you mean the MovementType? If unrestricted then it will scroll out of boundaries, if you set it to clamped or elastic (which is what you describe) then it stops at the end of the container. You can also enable/disable the vertical/horizontal scrolling so it only moves in one direction - Everts
@Everts Wow, this is an awesome solution, I didn't use ScrollRect, will use it now, thank you! If you will add info about ScrollRect and MovementType as an answer I'll accept it! - Rumata

2 Answers

2
votes

So you'd be better off with a ScrollRect as it already contains all the needed actions for this kind of feature.

MovementType will define how the system reacts when reaching the end of the container (from the documentation):

  • Unrestricted The content can move forever.
  • Elastic The content is allowed to temporarily move beyond the container, but is pulled back elastically.
  • Clamped The content can not be moved beyond its container.

Considering you have a long button system, maybe it needs to be dynamic, so you'd look into ContentSizeFitter.

You add a scroll view object. This will include by default:

  • Scrollview
  • Viewport
  • Content

Now add a Text component to the Content object, NOT a text child, a component to it. Also add a ContentSizeFitter and set the vertical fit to prefered size. This is because I will deal with vertical expansion.

Make sure the Viewport occupies the space that should serve as mask. For first practice, place the ScrollView object in the middle and set the anchors of Viewport to 0,1 so it takes the whole parent.

There is plenty more you can do and I would suggest to look into the free Unity UI extension library as it has some fancy accordeon or endless scrolling effects.

0
votes
  • Unrestricted The content can move forever. basically you can lose the content with a big scroll
  • Elastic The content is allowed to temporarily move beyond the container, but is pulled back elastically useless
  • Clamped The content can not be moved beyond its container useless