¿Cómo detecto la parte transparente de un sprite en unity
– UnityAssets3Free
hola , me llamo Juan y esta vez os traigo
esta pregunta
Tengo un sprite que es parcialmente transparente.
Mi objetivo es llenar la imagen con algunos prefabricados cuadrados.
Escribí este código que funciona bien.
while (newY < endVertical)
while (newX < endHorizontal)
Instantiate(filler, new Vector3(newX, newY, 0), Quaternion.identity);
newX += fillerWidth + 0.1f;
newY += fillerHeight + 0.1f;
newX = startHorizontal;
El resultado es
Sin embargo, mi objetivo es dibujar los prefabricados blancos solo en la parte visible de la imagen. Quiero que mi resultado sea algo como esto.
Para lograr esto, agregué un pequeño cambio para verificar el color en cada píxel y solo instanciar el prefabricado si el color no es claro.
var colorSelected = player.GetComponent<SpriteRenderer>().sprite.texture.GetPixel((int) newX, (int) newY);
if (colorSelected != Color.clear)
Instantiate(filler, new Vector3(newX, newY, 0), Quaternion.identity);
Esto, sin embargo, no funciona.
También probé esto
https://soporte.unity.com/hc/en-us/articles/206486626-How-can-I-get-pixels-from-ilegible-texturas-
Que también falla.
Descubrí que si puedo saber mediante programación si un píxel específico de mi imagen es transparente o no, entonces puedo averiguar el resto.
Alguien mire.
1 respuesta 1
Un pequeño aviso: Esto no será barato ^^
Querrá obtener los píxeles correspondientes en el rect donde va a generar un bloque y deberá verificarlos todos si ningún el de ellos es no totalmente transparente.
Dado que no proporcionó mucha información sobre su configuración, solo puedo intentar brindarle una solución basada en algunas suposiciones:
- Tu SpriteRenderer usa la textura completa
- O
filler
El pivote de está en la esquina inferior izquierda. - El relleno debe generarse en World Space (a diferencia del espacio de píxeles de un lienzo superpuesto de Screenspace, por ejemplo)
- No tiene en cuenta la rotación -> todo sucede en el plano xy 2D
Aquí está el script que usé.
using System;
using System.Linq;
using UnityEngine;
public class Example : MonoBehaviour
{
public GameObject filler;
public Vector2 fillerSize = Vector2.one * 0.5f;
public Vector2 spacing = Vector2.one * 0.1f;
public SpriteRenderer spriteRenderer;
[ContextMenu(nameof(Test))]
private void Test()
var sprite = spriteRenderer.sprite;
var texture = sprite.texture;
// get the world space dimensions
var worldBounds = spriteRenderer.bounds;
// get the pixel space dimensions
var pixelRect = sprite.rect;
// Multiply by this factor to convert world space size to pixels
var fillerSizeFactor = Vector2.one / worldBounds.size * pixelRect.size;
var fillerSizeInPixels = Vector2Int.RoundToInt(fillerSize * fillerSizeFactor);
var start = worldBounds.min;
var end = worldBounds.max;
// Use proper for loops instead of ugly and error prone while ;)
for (var worldY = start.y; worldY < end.y; worldY += fillerSize.y + spacing.y)
// convert the worldY to pixel coordinate
var pixelY = Mathf.RoundToInt((worldY - worldBounds.center.y + worldBounds.size.y / 2f) * fillerSizeFactor.y);
// quick safety check if this fits into the texture pixel space
if (pixelY + fillerSizeInPixels.y >= texture.height)
continue;
for (var worldX = start.x; worldX < end.x; worldX += fillerSize.x + spacing.x)
// convert worldX to pixel coordinate
var pixelX = Mathf.RoundToInt((worldX - worldBounds.center.x + worldBounds.size.x / 2f) * fillerSizeFactor.x);
// again the check if this fits into the texture pixel space
if (pixelX + fillerSizeInPixels.x >= texture.width)
continue;
// Cut out a rectangle from the texture at given pixel coordinates
var pixels = texture.GetPixels(pixelX, pixelY, fillerSizeInPixels.x, fillerSizeInPixels.y);
// Using Linq to check if all pixels are transparent
if (pixels.All(p => Mathf.Approximately(p.a, 0f)))
continue;
// otherwise spawn a filler here
Instantiate(filler, new Vector3(worldX, worldY, 0), Quaternion.identity, transform);
}
Resultado:
nota: si aun no se resuelve tu pregunta por favor dejar un comentario y pronto lo podremos de nuevo , muchas gracias
sin mas,espero que te halla servido