Search Unity

Unity UI Button with radial fill sprite only clickable on visible area?

Discussion in 'UGUI & TextMesh Pro' started by MikkoK-HS, Aug 23, 2018.

  1. MikkoK-HS

    MikkoK-HS

    Joined:
    Sep 26, 2017
    Posts:
    53
    I'm trying to create a dynamic radial menu where the amount of buttons can easily be changed. I had the idea of using a single circular sprite for the background of the buttons and adjusting the fill amount to create any size of button I need.

    However, I've run into a problem. The clickable area of the buttons seems to cover the entire sprite, not just the area that is visible according to the fill amount. I tried setting Image.alphaHitTestMinimumThreshold to more than zero but it doesn't affect the areas of the sprite hidden by fill amount, just the areas that are transparent in the original sprite. I also tried adding a mask that would hide parts of the button, but apparently you can click buttons even through a mask, which seems a bit weird to me.

    Is there a way to create a button that uses a radial fill sprite, where only the visible are is clickable?
     
  2. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
  3. MikkoK-HS

    MikkoK-HS

    Joined:
    Sep 26, 2017
    Posts:
    53
    @Hosnkobf
    Hey thanks for the tip, that solved it. You had me scared there but it only needed some very basic vector math.

    What I did was I calculated the origin vector and the click point vector, then compared the angle between those vectors to the fill amount.
     
    Hosnkobf likes this.
  4. Deleted User

    Deleted User

    Guest

    I don't understand what it is you did exactly to solve your issue either. Could someone provide an code example, or explain a little more in depth more on how I can calculate the angle between the original vector and the click point vector and implement it into a script that'll only make the fill areas clickable?
     
    Last edited by a moderator: Nov 19, 2021
  5. BadToxic

    BadToxic

    Joined:
    Apr 6, 2015
    Posts:
    4
    For anyone struggling with the same problem, here the solution:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. public class ImageFilledClickableSlices : Image {
    5.     public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera) {
    6.         bool result = base.IsRaycastLocationValid(screenPoint, eventCamera);
    7.         if (!result) {
    8.             return false;
    9.         }
    10.         Vector2 localPoint;
    11.         RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out localPoint);
    12.         float clickAngle = Vector2.SignedAngle(localPoint, new Vector2(0, -1));
    13.         return (clickAngle >= 0) && (clickAngle < (360f * fillAmount));
    14.     }
    15. }
     
  6. Arthur-LVGameDev

    Arthur-LVGameDev

    Joined:
    Mar 14, 2016
    Posts:
    228
    This should get added to the base/core UI code -- no reason not to, it isn't expensive (at least relative to existing alpha test capabilities), and I think it'd be very helpful for many developers to have this be built-in & work directly out of the box!
     
  7. Klausbdl

    Klausbdl

    Joined:
    Aug 12, 2013
    Posts:
    65
    So, to me the float "clickAngle" was returning a value between [0,180] when the cursor is bellow 0.5 of the fillAmount, and then from [-180, 0] when above 0.5 fillAmount. This was causing to only detect the cursor halfway through the button. To fix it, I just added this code right before the return:
    if (clickAngle < 0) clickAngle += 360;