-
-
Save emredesu/af597de14a4377e1ecf96b6f7b6cc506 to your computer and use it in GitHub Desktop.
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.EventSystems; | |
using UnityEngine.UI; | |
using UnityEngine.InputSystem; | |
[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() { | |
// If we are on mobile and we do not have a gamepad connected, do not do anything. | |
if (SystemInfo.deviceType == DeviceType.Handheld && Gamepad.all.Count <= 1) { | |
return; | |
} | |
// 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; | |
} | |
} | |
#nullable enable | |
void InputScroll() { | |
if (m_Selectables.Count > 0) { | |
Keyboard? currentKeyboard = Keyboard.current; | |
Gamepad? currentGamepad = Gamepad.current; | |
if (currentKeyboard != null) { | |
if (Keyboard.current.upArrowKey.isPressed || Keyboard.current.downArrowKey.isPressed) { | |
ScrollToSelected(false); | |
} | |
} | |
if (currentGamepad != null) { | |
if (Gamepad.current.dpad.up.isPressed || Gamepad.current.dpad.down.isPressed) { | |
ScrollToSelected(false); | |
} | |
} | |
} | |
} | |
#nullable disable | |
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); | |
} | |
} |
could you explain to me how you made it work with the new input system please?
I used a C# event workflow for the new input system.
In it input methods look like this: void SomeMethod (InputAction.CallbackContext context)
I just check the context to get direction.
if (context.ReadValue<Vector2>().y > 0.1f)
That's up input, since y is above 0!
(I just put it at 0.1 for a bit of extra deadzone for controllers.)
And of course for left/right you just check context.ReadValue<Vector2>().x
The reason it was "currContext" above is because my input system is on a separate script, I just stored context in that variable.
I used a C# event workflow for the new input system. In it input methods look like this:
void SomeMethod (InputAction.CallbackContext context)
I just check the context to get direction.
if (context.ReadValue<Vector2>().y > 0.1f)
That's up input, since y is above 0! (I just put it at 0.1 for a bit of extra deadzone for controllers.)And of course for left/right you just check
context.ReadValue<Vector2>().x
The reason it was "currContext" above is because my input system is on a separate script, I just stored context in that variable.
thanks for the quick reply, I tried something similar but got weird results, gonna see what I can do in the morning ,its almost midnight
Rimec commented that they used scroll.verticalNormalizedPosition = (1 - ((selectedIndex / 7) / ((((float)selectables.Count) / 7) - 1)));
With 7 being the width, to make an another branch of this work with grids of 7 width.
...But I really like how your version uses input to check for vertical vs horizontal instead!
My game uses new input system and rebindable keys, so I decided to use:
if (Mathf.Abs(currContext.ReadValue().y) > Mathf.Abs(currContext.ReadValue().x))
With currContext being InputAction.CallbackContext.
That way it's not hardcoded to specific keys.
Thanks, this was the easiest one to get working in my game!