How to stop non-rectangular buttons from overlapping?

I’m trying to figure out how to use Unity’s new UI system, and I’ve run into a problem. It seems that it only allows rectangles to be buttons.

What I want to do is have a circle sliced into 7 parts, where each part is clickable (see image). However, when I attempt this, the rectangle of the button of one slice overlap the images of other slices.

Is there any way to fix this using the UI system of Unity?

[39304-round+menu.png|39304]

I found another (probably better) solution for this problem. I used a Collider2D (PolygonCollider2D) to define the clickable shape and then used this RaycastFilter:

using UnityEngine;
using UnityEngine.UI;
 
[RequireComponent (typeof (RectTransform), typeof (Collider2D))]
public class Collider2DRaycastFilter : MonoBehaviour, ICanvasRaycastFilter 
{
	Collider2D myCollider;
	RectTransform rectTransform;
	
	void Awake () 
	{
		myCollider = GetComponent<Collider2D>();
		rectTransform = GetComponent<RectTransform>();
	}
 
#region ICanvasRaycastFilter implementation
	public bool IsRaycastLocationValid (Vector2 screenPos, Camera eventCamera)
	{
		var worldPoint = Vector3.zero;
		var isInside = RectTransformUtility.ScreenPointToWorldPointInRectangle(
			rectTransform,
			screenPos,
			eventCamera,
			out worldPoint
		);
		if (isInside)
			isInside = myCollider.OverlapPoint(worldPoint);
		return isInside;
	}
#endregion
}

Using a collider for this is a bit hacky but the result is much simpler, probably faster and makes it much easier to adjust the clickable shape.

This could be improved by creating a custom alternative to replace the Collider2D but that’s a bit too much work for what I need.

For some reason (don’t ask me why) the faq of Unity UI is almost unknown to google, while it has a lot of information that is rather usefull :stuck_out_tongue:

For you, this part is something I think you are looking for:

How do I make UI elements have non-rectangular hitboxes?

Add a component that implements ICanvasRaycastFilter. In your implementation of IsRaycastLocationValid, reject all points that are ‘outside’ your custom hitbox shape. It’s up to you how you want to do that, but for example for a circular hitbox you could measure the distance between the point and your object’s center and reject the point if that distance is greater than your circle’s radius. Or perhaps you could look up the alpha value of the pixel the hit is on, as per this script by senritsu.

Sadly, the link over there is broken :frowning: However, using google I was able to find this…

Forum post: http://forum.unity3d.com/threads/none-rectangle-shaped-button.263684

Download link: http://forum.unity3d.com/attachments/raycastmask-cs.110370/

The only way i can think that you can do this is by not using the new UI and using a system of another camera, and Sprites which have custom scripts to detect clicks and hovers using OnMouseOver and OnMouseDown. (Make sure the sprites have 2d colliders too!

Soo for example:

using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour {
    //This may or may not work, this is just to illustrate.

    public Color MouseOverColor;
    public Sprite sprite;

    private Color startColor;

    void Start(){
        startColor = sprite.color;
    }

    void OnMouseOver(){
    //For example change the button color when moused over
        sprite.color = MouseOverColor;
    }
    
    void OnMouseExit(){
    //To revert the color on the mouse exiting.
        sprite.color = oldColor;
    }
    
    void OnMouseUpAsButton(){
        //This is called when the mouse is released over the same
        //collider as it was pressed on, great for buttons.
        DoThing();
    }
}

I recently came across this and found the answers here on this forum to be a great starting point! I consolidated and updated the info into a concise blog post:

Non-Rectangular UI Buttons in Unity