En este momento estás viendo ¿Cómo detecto la parte transparente de un sprite en unity

 – Unity

¿Cómo detecto la parte transparente de un sprite en unity – Unity

¿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 fillerEl 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

Deja una respuesta