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. Dismiss Notice

Making rounded corner texture generator, some corners have slightly different corner radius?

Discussion in 'Scripting' started by thevvulf, Dec 6, 2021.

  1. thevvulf

    thevvulf

    Joined:
    Oct 31, 2020
    Posts:
    36
    I'm making a script that lets me make UI elements with rounded corners. Heres the entire script since I have no clue where the problem originates from:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. [ExecuteAlways]
    5. public class RoundedRectangle : MonoBehaviour
    6. {
    7.     public int cornerRadius;
    8.     [Space]
    9.     public Color color;
    10.    
    11.     RectTransform rt;
    12.     Texture2D tex;
    13.  
    14.     Rect innerRect;
    15.     Rect xSpanRect;
    16.     Rect ySpanRect;
    17.  
    18.     Vector2 center;
    19.  
    20.     float width;
    21.     float height;
    22.  
    23.     Vector2 innerTL;
    24.     Vector2 innerTR;
    25.     Vector2 innerBL;
    26.     Vector2 innerBR;
    27.    
    28.     void Start() {
    29.         rt = GetComponent<RectTransform>();
    30.         width = rt.sizeDelta.x * rt.localScale.x;
    31.         height = rt.sizeDelta.y * rt.localScale.y;
    32.  
    33.         tex = new Texture2D(Mathf.RoundToInt(width), Mathf.RoundToInt(height));
    34.         tex.filterMode = FilterMode.Point;
    35.         tex.Apply();
    36.         GetComponent<RawImage>().texture = tex;
    37.         center = new Vector2(width * 0.5f, height * 0.5f);
    38.     }
    39.    
    40.     void Update() {
    41.         innerRect = new Rect(width * 0.5f, height * 0.5f, width - (cornerRadius * 2), height - (cornerRadius * 2));
    42.        
    43.         innerTL = new Vector2((-(width * 0.5f)) + cornerRadius, (height * 0.5f) - cornerRadius);
    44.         innerTR = new Vector2(((width * 0.5f)) - cornerRadius, (height * 0.5f) - cornerRadius);
    45.         innerBL = new Vector2((-(width * 0.5f)) + cornerRadius, -(height * 0.5f) + cornerRadius);
    46.         innerBR = new Vector2(((width * 0.5f)) - cornerRadius, -(height * 0.5f) + cornerRadius);
    47.  
    48.         innerRect.position = new Vector2(cornerRadius, cornerRadius);
    49.         innerRect.width = width - (cornerRadius * 2);
    50.         innerRect.height = height - (cornerRadius * 2);
    51.  
    52.         xSpanRect = new Rect(0, cornerRadius, width, innerRect.height);
    53.         ySpanRect = new Rect(cornerRadius, 0, innerRect.width, height);
    54.  
    55.         for (int x = 0; x < tex.width; x++) {
    56.             for (int y = 0; y < tex.height; y++) {
    57.                 Vector2 pos = new Vector2(x - (width * 0.5f), y - (height * 0.5f));
    58.                 //corners
    59.                 if(Vector2.Distance(pos, innerTL) <= cornerRadius || Vector2.Distance(pos, innerTR) <= cornerRadius || Vector2.Distance(pos, innerBL) <= cornerRadius || Vector2.Distance(pos, innerBR) <= cornerRadius){
    60.                     tex.SetPixel(x, y, color);
    61.                 }else{
    62.                     tex.SetPixel(x, y, Color.clear);
    63.                 }
    64.                 //insides
    65.                 if(xSpanRect.Contains(new Vector2(x, y)) || ySpanRect.Contains(new Vector2(x, y))){
    66.                     tex.SetPixel(x, y, color);
    67.                 }
    68.             }
    69.         }
    70.         tex.Apply();
    71.     }
    72. }
    73.  
    All I do is have 3 rects. One that is responsible for drawing the corners, where the width and height are the current scripts width and height - (cornerRadius * 2) so its even on both sides. I use this first one do draw the circles on the corners by checking the distance from the current point to the nearest corner. I then have 2 more rects, the xSpanRect and the ySpanRect, each responsible for filling in the rest of the rectangle. This works fine and looks decent, except for one small problem:


    You can see that the corner radius on the top right corner is larger than it should be. This happens on every single one I've tested and with every different corner radius. I've looked over my code more than santa checks his list and I haven't found the culprit. Any ideas for what could be causing this?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    Probably rounding... your query is based on the coordinate in line 57, that coordinate is the lower-left corner of each pixel, not the center.

    Might work better if line 57 above became:

    Code (csharp):
    1. Vector2 pos = new Vector2(
    2.  (x + 0.5f) - (width * 0.5f),
    3.  (y + 0.5f) - (height * 0.5f));
     
  3. thevvulf

    thevvulf

    Joined:
    Oct 31, 2020
    Posts:
    36
    kurt dekker saves the day again
     
    Kurt-Dekker likes this.