Skip to content

Instantly share code, notes, and snippets.

@spireggs
Forked from mandarinx/ScrollRectAutoScroll.cs
Last active January 8, 2024 18:28
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save spireggs/2b8221a2961f2352542fad8f9a9dc07e to your computer and use it in GitHub Desktop.
Save spireggs/2b8221a2961f2352542fad8f9a9dc07e to your computer and use it in GitHub Desktop.
Unity3d ScrollRect Auto-Scroll, Dropdown Use: Places this component in the Template of Dropdown (with the ScrollRect component)
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
//comment the next line out if you aren't using Rewired
using Rewired;
[RequireComponent(typeof(ScrollRect))]
public class ScrollRectAutoScroll : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public float scrollSpeed = 10f;
private bool mouseOver = false;
private List<Selectable> m_Selectables = new List<Selectable>();
private ScrollRect m_ScrollRect;
private Vector2 m_NextScrollPosition = Vector2.up;
public int RewiredPlayerID = 0;
private Player rePlayer;
void OnEnable()
{
if (m_ScrollRect)
{
m_ScrollRect.content.GetComponentsInChildren(m_Selectables);
}
}
void Awake()
{
m_ScrollRect = GetComponent<ScrollRect>();
//remove this line if not using Rewired
rePlayer = ReInput.players.GetPlayer(RewiredPlayerID);
}
void Start()
{
if (m_ScrollRect)
{
m_ScrollRect.content.GetComponentsInChildren(m_Selectables);
}
ScrollToSelected(true);
}
void Update()
{
// Scroll via input.
InputScroll();
if (!mouseOver)
{
// Lerp scrolling code.
m_ScrollRect.normalizedPosition = Vector2.Lerp(m_ScrollRect.normalizedPosition, m_NextScrollPosition, scrollSpeed * Time.unscaledDeltaTime);
}
else
{
m_NextScrollPosition = m_ScrollRect.normalizedPosition;
}
}
void InputScroll()
{
if (m_Selectables.Count > 0)
{
//remove the rePlayer getaxis calls is you aren't using Rewired
//if it still doesn't work, check your input manager settings's axes and make sure they are defined properly
//if you're using the new input system, this is also probably where you should replace the calls to the old one
if (rePlayer.GetAxis("MoveHorizontal") != 0.0f || rePlayer.GetAxis("MoveVertical") != 0f
|| Input.GetAxis("Vertical") != 0.0f || Input.GetAxis("Horizontal") != 0.0f || Input.GetButtonDown("Horizontal")
|| Input.GetButtonDown("Vertical") || Input.GetButton("Horizontal") || Input.GetButton("Vertical"))
{
ScrollToSelected(false);
}
}
}
void ScrollToSelected(bool quickScroll)
{
int selectedIndex = -1;
Selectable selectedElement = EventSystem.current.currentSelectedGameObject ? EventSystem.current.currentSelectedGameObject.GetComponent<Selectable>() : null;
if (selectedElement)
{
selectedIndex = m_Selectables.IndexOf(selectedElement);
}
if (selectedIndex > -1)
{
if (quickScroll)
{
m_ScrollRect.normalizedPosition = new Vector2(0, 1 - (selectedIndex / ((float)m_Selectables.Count - 1)));
m_NextScrollPosition = m_ScrollRect.normalizedPosition;
}
else
{
m_NextScrollPosition = new Vector2(0, 1 - (selectedIndex / ((float)m_Selectables.Count - 1)));
}
}
}
public void OnPointerEnter(PointerEventData eventData)
{
mouseOver = true;
}
public void OnPointerExit(PointerEventData eventData)
{
mouseOver = false;
ScrollToSelected(false);
}
}
@TubyUwU
Copy link

TubyUwU commented Nov 30, 2021

THANKS!

@GamsDataTaboo
Copy link

This was really helpful, thank you!

@xXjoakinXx
Copy link

2022 and still being helpful ❤️

@AlexandrDarii
Copy link

❤️

@Rimec
Copy link

Rimec commented May 28, 2023

For those who want to use this and have a grid of elements, you can solve this by dividing selectedIndex and m_Selectables.Count by the number of items in a row, for 7 items it would look like this:
scroll.verticalNormalizedPosition = (1 - ((selectedIndex / 7) / ((((float)selectables.Count) / 7) - 1)));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment