6

Please see the image attached to understand me. You can see Button One and Button two. But unfortunately buttons are always rectangular but i want it to be parallelogram shape.

Image attached

Please help me guys

3 Answers 3

8

This was already done before and is still working

Checkout this thread.

The setup:

Adjust your shape texture and make it

  • As usual a Sprite (2D and UI)
  • MeshType = Full Rect
  • Read/Write Enabled = true

enter image description here

Put your buttons under a Mask object so you have a hierarchy like

Canvas
|---MaskObject1 (with trapez texture)
|   |---Button1
|
|---MaskObject2
    |---Button2

On your Mask have an additional component RaycastMask.

The script looks like this

using UnityEngine;
using UnityEngine.UI;
 
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(Image))]
public class RaycastMask : MonoBehaviour, ICanvasRaycastFilter
{
    private Image _image;
    private Sprite _sprite;
 
    void Start ()
    {
        _image = GetComponent<Image>();
    }
 
    public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
    {
        _sprite = _image.sprite;
 
        var rectTransform = (RectTransform)transform;
        Vector2 localPositionPivotRelative;
        RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform) transform, sp, eventCamera, out localPositionPivotRelative);
 
        // convert to bottom-left origin coordinates
        var localPosition = new Vector2(localPositionPivotRelative.x + rectTransform.pivot.x*rectTransform.rect.width,
            localPositionPivotRelative.y + rectTransform.pivot.y*rectTransform.rect.height);
     
        var spriteRect = _sprite.textureRect;
        var maskRect = rectTransform.rect;
 
        var x = 0;
        var y = 0;
        // convert to texture space
        switch (_image.type)
        {
         
            case Image.Type.Sliced:
            {
                var border = _sprite.border;
                // x slicing
                if (localPosition.x < border.x)
                {
                    x = Mathf.FloorToInt(spriteRect.x + localPosition.x);
                }
                else if (localPosition.x > maskRect.width - border.z)
                {
                    x = Mathf.FloorToInt(spriteRect.x + spriteRect.width - (maskRect.width - localPosition.x));
                }
                else
                {
                    x = Mathf.FloorToInt(spriteRect.x + border.x +
                                         ((localPosition.x - border.x)/
                                         (maskRect.width - border.x - border.z)) *
                                         (spriteRect.width - border.x - border.z));
                }
                // y slicing
                if (localPosition.y < border.y)
                {
                    y = Mathf.FloorToInt(spriteRect.y + localPosition.y);
                }
                else if (localPosition.y > maskRect.height - border.w)
                {
                    y = Mathf.FloorToInt(spriteRect.y + spriteRect.height - (maskRect.height - localPosition.y));
                }
                else
                {
                    y = Mathf.FloorToInt(spriteRect.y + border.y +
                                         ((localPosition.y - border.y) /
                                         (maskRect.height - border.y - border.w)) *
                                         (spriteRect.height - border.y - border.w));
                }
            }
                break;
            case Image.Type.Simple:
            default:
                {
                    // conversion to uniform UV space
                    x = Mathf.FloorToInt(spriteRect.x + spriteRect.width * localPosition.x / maskRect.width);
                    y = Mathf.FloorToInt(spriteRect.y + spriteRect.height * localPosition.y / maskRect.height);
                }
                break;
        }
 
        // 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;
        }
    }
}

The result looks like

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

3

You can have the same result with 1 line of code adding a new script on your Button:

  1. within this script, on Start() just write:

    GetComponent<Image>().alphaHitTestMinimumThreshold = 0.1f;
    
  2. But you need to change the settings of your image as mentioned above:

    • Sprite (2D and UI)
    • MeshType = Full Rect
    • Read/Write Enabled = true
  3. Link to the tutorial: https://www.youtube.com/watch?v=8QxN7hQXkO8

Comments

-1

In your Button source Image, in your Button component, you can use the UISprite default button sprite of Unity for the button.

If you go to your Canvas Game Object | Canvas Scaler Component / Reference Pixels Per Unit and increase the value, the button will be more rounded, if you decrease the value the button will be more rectangular.

1 Comment

This will not answer OP's question how to get differently shaped buttons regarding to not how they are rendered but rather how they are interacting though ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.