Unity中如何实现适配矩形纹理的非正方形径向渐变填充函数
Hey, I’ve run into this exact issue when working on UI gradient textures in Unity! Your current radial gradient only works for squares because you’re using texture.width to normalize the distance from the center—this doesn’t account for different width/height ratios, so the gradient gets stretched on rectangles. Let’s fix that.
The Core Problem
When you calculate distanceFromCenter / texture.width, you’re assuming the texture’s width and height are equal. On a rectangle, this makes the distance calculation biased toward the wider axis, leading to an elliptical or misaligned fade instead of a uniform radial effect.
Solution 1: Uniform Circular Gradient (Fits Inside Rectangle)
If you want a perfect circular gradient that fits neatly inside the rectangle (touching the midpoints of the longest edges), we need to normalize the pixel coordinates to a square coordinate space first. Here’s the modified code:
Vector2 center = new Vector2(texture.width * 0.5f, texture.height * 0.5f); float aspectRatio = (float)texture.width / texture.height; for (int y = 0; y < texture.height; y++) { for (int x = 0; x < texture.width; x++) { // Convert pixel position to normalized coordinates centered at (0,0) float normX = (x - center.x) / texture.width; float normY = (y - center.y) / texture.height; // Correct coordinates to maintain square aspect ratio if (aspectRatio > 1) { // Wide texture: compress X-axis to match Y-axis scale normX /= aspectRatio; } else { // Tall texture: compress Y-axis to match X-axis scale normY *= aspectRatio; } // Calculate normalized distance (0 at center, 1 at farthest edge of the circle) float distance = new Vector2(normX, normY).magnitude * 2; // Adjust t value based on your invert flag, clamp to 0-1 to prevent color errors float t = invert ? 1 - Mathf.Clamp01(distance) : Mathf.Clamp01(distance); texture.SetPixel(x, y, gradient.Evaluate(t)); } }
How This Works:
- Normalized Coordinates: We shift the pixel position to be relative to the texture center, then scale it to a -0.5 to 0.5 range for both axes.
- Aspect Ratio Correction: We adjust the wider axis to match the scale of the narrower one, creating a square coordinate space. This ensures the distance calculation is uniform in all directions.
- Distance Calculation: Multiplying the magnitude by 2 converts the range from 0-0.5 to 0-1, which matches the expected input for Unity’s
Gradient.Evaluate().
Solution 2: Elliptical Gradient (Fits Entire Rectangle)
If you want the gradient to stretch to fit the entire rectangle (forming an ellipse that touches all four corners), skip the aspect ratio correction. Instead, normalize each axis independently:
Vector2 center = new Vector2(texture.width * 0.5f, texture.height * 0.5f); for (int y = 0; y < texture.height; y++) { for (int x = 0; x < texture.width; x++) { // Normalize each axis relative to its own dimension float normX = (x - center.x) / texture.width; float normY = (y - center.y) / texture.height; // Distance here accounts for the rectangle's aspect ratio float distance = new Vector2(normX, normY).magnitude * 2; float t = invert ? 1 - Mathf.Clamp01(distance) : Mathf.Clamp01(distance); texture.SetPixel(x, y, gradient.Evaluate(t)); } }
This version will make the gradient fade evenly from the center to all four edges of the rectangle, matching its shape perfectly.
Quick Note
I added Mathf.Clamp01() to ensure t never goes outside the 0-1 range—this prevents unexpected color behavior if the distance calculation ever exceeds the expected bounds (e.g., edge pixels on odd-sized textures).
内容的提问来源于stack exchange,提问作者user3915050

