As you can see, I have a scroll view that is filled with Buttons and the scroll view works as expected except one thing.
If the mouse is hovering over a button, then I can’t scroll with the MouseWheel.
If the mouse is in the space between the buttons, then scrolling works.
I know this must be the intended behavior as raycasts are blocked by the buttons. But it makes navigating the scroll view harder.
Is there any way to overcome this?
Not sure if my answer in this thread also works for the mouse wheel, but i think it does:
It’s been a few years since you asked. But if anyone else has this issue, I wrote some code to address it.
Create a subclass of ScrollRect, and use it where you would normally use a ScrollRect. It also amplifies the mouse wheel, because the default is very slow. Here’s the code:
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ChiScrollRect : ScrollRect, IPointerEnterHandler, IPointerExitHandler
{
private static string mouseScrollWheelAxis = "Mouse ScrollWheel";
private bool swallowMouseWheelScrolls = true;
private bool isMouseOver = false;
public void OnPointerEnter(PointerEventData eventData)
{
isMouseOver = true;
}
public void OnPointerExit(PointerEventData eventData)
{
isMouseOver = false;
}
private void Update()
{
// Detect the mouse wheel and generate a scroll. This fixes the issue where Unity will prevent our ScrollRect
// from receiving any mouse wheel messages if the mouse is over a raycast target (such as a button).
if (isMouseOver && IsMouseWheelRolling())
{
var delta = UnityEngine.Input.GetAxis(mouseScrollWheelAxis);
PointerEventData pointerData = new PointerEventData(EventSystem.current);
pointerData.scrollDelta = new Vector2(0f, delta);
swallowMouseWheelScrolls = false;
OnScroll(pointerData);
swallowMouseWheelScrolls = true;
}
}
public override void OnScroll(PointerEventData data)
{
if (IsMouseWheelRolling() && swallowMouseWheelScrolls)
{
// Eat the scroll so that we don't get a double scroll when the mouse is over an image
}
else
{
// Amplify the mousewheel so that it matches the scroll sensitivity.
if (data.scrollDelta.y < -Mathf.Epsilon)
data.scrollDelta = new Vector2(0f, -scrollSensitivity);
else if (data.scrollDelta.y > Mathf.Epsilon)
data.scrollDelta = new Vector2(0f, scrollSensitivity);
base.OnScroll(data);
}
}
private static bool IsMouseWheelRolling()
{
return UnityEngine.Input.GetAxis(mouseScrollWheelAxis) != 0;
}
}
Well this is exactly what i’ve searched for a lot of time, i’m just wondering why we do no get more acces and details on this from Unity team itself, i mean having to write custom things to scroll in a scrollview that is already made is kinda wierd, @kmeboe u’re a hero
Thank you so much!
Thanks, @kmeboe ! This is very helpful.
Small note about handling the OnPointerExit event. It seems that this event is sometimes triggered even when the mouse is still inside the ScrollRect (but focus has shifted to a child object). I found that I had to check eventData.fullyExited to get this working correctly.
Like this:
public void OnPointerExit(PointerEventData eventData)
{
if (eventData.fullyExited)
{
isMouseOver = false;
}
}
Edit: Actually, eventData.fullyExited may not work the way I expected so I’m not sure this is correct. But it’s working in my limited scenario so I’m sticking to it for now.
thanks ive been looking for this for way too long
