Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Unity UI Scroll View does not scroll with MouseWheel when mouse is over a button inside the scroll view?

Discussion in 'UGUI & TextMesh Pro' started by TheGameNewBie, Mar 18, 2020.

  1. TheGameNewBie

    TheGameNewBie

    Joined:
    Jul 27, 2017
    Posts:
    92
    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?
    Capture.PNG
     
  2. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,078
    Not sure if my answer in this thread also works for the mouse wheel, but i think it does:
     
  3. kmeboe

    kmeboe

    Joined:
    Jul 17, 2012
    Posts:
    2
    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:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3. using UnityEngine.UI;
    4.  
    5. public class ChiScrollRect : ScrollRect, IPointerEnterHandler, IPointerExitHandler
    6. {
    7.     private static string mouseScrollWheelAxis = "Mouse ScrollWheel";
    8.     private bool swallowMouseWheelScrolls = true;
    9.     private bool isMouseOver = false;
    10.  
    11.     public void OnPointerEnter(PointerEventData eventData)
    12.     {
    13.         isMouseOver = true;
    14.     }
    15.  
    16.     public void OnPointerExit(PointerEventData eventData)
    17.     {
    18.         isMouseOver = false;
    19.     }
    20.  
    21.     private void Update()
    22.     {
    23.         // Detect the mouse wheel and generate a scroll. This fixes the issue where Unity will prevent our ScrollRect
    24.         // from receiving any mouse wheel messages if the mouse is over a raycast target (such as a button).
    25.         if (isMouseOver && IsMouseWheelRolling())
    26.         {
    27.             var delta = UnityEngine.Input.GetAxis(mouseScrollWheelAxis);
    28.  
    29.             PointerEventData pointerData = new PointerEventData(EventSystem.current);
    30.             pointerData.scrollDelta = new Vector2(0f, delta);
    31.  
    32.             swallowMouseWheelScrolls = false;
    33.             OnScroll(pointerData);
    34.             swallowMouseWheelScrolls = true;
    35.         }
    36.     }
    37.  
    38.     public override void OnScroll(PointerEventData data)
    39.     {
    40.         if (IsMouseWheelRolling() && swallowMouseWheelScrolls)
    41.         {
    42.             // Eat the scroll so that we don't get a double scroll when the mouse is over an image
    43.         }
    44.         else
    45.         {
    46.             // Amplify the mousewheel so that it matches the scroll sensitivity.
    47.             if (data.scrollDelta.y < -Mathf.Epsilon)
    48.                 data.scrollDelta = new Vector2(0f, -scrollSensitivity);
    49.             else if (data.scrollDelta.y > Mathf.Epsilon)
    50.                 data.scrollDelta = new Vector2(0f, scrollSensitivity);
    51.  
    52.             base.OnScroll(data);
    53.         }
    54.     }
    55.  
    56.     private static bool IsMouseWheelRolling()
    57.     {
    58.         return UnityEngine.Input.GetAxis(mouseScrollWheelAxis) != 0;
    59.     }
    60. }
     
  4. VIV-prod

    VIV-prod

    Joined:
    Aug 23, 2021
    Posts:
    4
    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
     
    kmeboe likes this.
  5. yengNami

    yengNami

    Joined:
    Feb 14, 2021
    Posts:
    14
    -
    Thank you so much!
     
    kmeboe likes this.
  6. apparition

    apparition

    Joined:
    Jan 11, 2012
    Posts:
    116
    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:
    Code (CSharp):
    1. public void OnPointerExit(PointerEventData eventData)
    2. {
    3.     if (eventData.fullyExited)
    4.     {
    5.         isMouseOver = false;
    6.     }
    7. }
    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.
     
    Last edited: Jun 21, 2023
    kmeboe likes this.