-
-
Save mandarinx/eae10c9e8d1a5534b7b19b74aeb2a665 to your computer and use it in GitHub Desktop.
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.EventSystems; | |
using UnityEngine.UI; | |
[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; | |
void OnEnable() | |
{ | |
if (m_ScrollRect) | |
{ | |
m_ScrollRect.content.GetComponentsInChildren(m_Selectables); | |
} | |
} | |
void Awake() | |
{ | |
m_ScrollRect = GetComponent<ScrollRect>(); | |
} | |
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.deltaTime); | |
} | |
else | |
{ | |
m_NextScrollPosition = m_ScrollRect.normalizedPosition; | |
} | |
} | |
void InputScroll() | |
{ | |
if (m_Selectables.Count > 0) | |
{ | |
if (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); | |
} | |
} |
@mandarinx I got back to the code because it confused me why it wouldn't actually center on the selected option on option change.
Imho, You may be missing:
m_ScrollRect.normalizedPosition = m_NextScrollPosition;
after line 76
since You set the new m_NextScrollPosition but never tell the RectTransform to use the new position after the input
I created an account just to thank you for this script. I tried lots of things before finding this and none of them worked.
For anyone who has the same issue as me, I had to add this else in the InputScroll method:
else
{
ScrollToSelected(true);
}
The issue happened when this script was attatched to the template of a TMP_Dropdown which is part of a prefab that gets instantiated in runtime, it wouldn't scroll when I pressed down or up, but that else fixed it :)
@PostleService That's because Unity hasn't touched their own UI system in 5 years. :-)