3
\$\begingroup\$

I have been using unity and C# scripting now for the past 2 or 3 weeks. So yeah i am very new to unity and C#.

I wanted to know if there is a way to make a round(circle) button without using the rect.

The problem I have now, I am using a 2d sprite to make the button appear round, however when you hover or click with in the rect, it still works.

I saw this asset in the asset store called Alpha Raycaster

Check asset out: Alpha Raycaster on Unity Asset Store

I cannot afford to pay for it right now so I was wondering if there is a free alternative to the Alpha Raycaster for now.

Dose anyone know how we can solve this issue? I obviously only want the button to function when the user hovers or clicks within the sprite and NOT on the alpha surrounding the sprite.

\$\endgroup\$
  • \$\begingroup\$ Does a CircleCollider2D not do the job for you? \$\endgroup\$ – DMGregory Jun 11 at 11:45
  • \$\begingroup\$ @DMGregory I dont know how to implent it. Because I have added the circle collider to the button. but I dont know what else to do after that. \$\endgroup\$ – Designs By Cornelius Jun 11 at 12:15
  • \$\begingroup\$ This may help you: forum.unity.com/threads/… They use ICanvasRaycastFilter interface to override where raycast hit and where doesn't. \$\endgroup\$ – trollingchar Jun 11 at 12:16
  • \$\begingroup\$ Try showing us how you've implemented your button so far. There's more than one way to make a button in Unity, so we'll need to see what you're doing to know where to plug in changes. \$\endgroup\$ – DMGregory Jun 11 at 12:37
3
\$\begingroup\$

There is one easy way that only works for round Shapes. In your Button callback you could test the distance of the mouse from the center of the button against the radius of the button and only trigger the click or hoover effect when it is within the buttons radius.

But since you are new, maybe focus on making some gameplay rather than the button design. While a good look and feel are important, i believe a working game will motivate you more. Try focusing on what you can do, instead of what you can't.

\$\endgroup\$
  • 1
    \$\begingroup\$ Yeah thanks I was looking at doing the math for that. Even though it may work for the actual functionality, it still doesnt affect the hover state, so unless i change the actual hover animation. then that will be okay. What about the circle collider 2d. Do you know how I could use that maybe becuase saw a post about the circle collider \$\endgroup\$ – Designs By Cornelius Jun 11 at 11:30
2
\$\begingroup\$

YES! THANK YOU @trollingchar.

I added the code to a script and attached the script to the button. that is exactly the functionality i was looking for.

check out the link to the code: https://forum.unity.com/threads/none-rectangle-shaped-button.263684/#post-2146709

using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(Image))]
public class RaycastMask : MonoBehaviour, ICanvasRaycastFilter
{
    private Sprite _sprite;

    void Start ()
    {
        _sprite = GetComponent<Image>().sprite;
    }

    public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
    {
        var rectTransform = (RectTransform)transform;
        Vector2 local;
        RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform) transform, sp, eventCamera, out local);
        // normalize local coordinates
        var normalized = new Vector2(
            (local.x + rectTransform.pivot.x*rectTransform.rect.width)/rectTransform.rect.width,
            (local.y + rectTransform.pivot.y*rectTransform.rect.height)/rectTransform.rect.width);
        // convert to texture space
        var rect = _sprite.textureRect;
        var x = Mathf.FloorToInt(rect.x + rect.width * normalized.x);
        var y = Mathf.FloorToInt(rect.y + rect.height * normalized.y);
        // destroy component if texture import settings are wrong
        try
        {
            return _sprite.texture.GetPixel(x,y).a > 0;
        }
        catch (UnityException e)
        {
            Debug.LogError("Mask texture not readable, set your sprite to Texture Type 'Advanced' and check 'Read/Write Enabled'");
            Destroy(this);
            return false;
        }
    }
}

for those that are too lazy to follow the link :) here is the code snippet.

It was posted by @senritsu

if i could hug you right now i would :)

\$\endgroup\$
1
\$\begingroup\$

This is much simpler than it seems. Unity has functionality built in for this.

theButton.alphaHitTestMinimumThreshold = 0.5f;

Documentation

What this does is only register hits from the raycast if the pixel hit has an alpha of 0.5 or greater.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.