Search code examples
unity-game-enginesprite

How to clear the pixel of a spriterenderer ata given world position


I have a sprite renderer scaled to fill screen and i need to clear the pixel at a given world position.

I have tried converting world position to screenpoint but it is displaced,the farther the coord the difference is bigger between the world position and the convertion, i suppose i have to use some math algorithm but i am not good at it.


Solution

  • To accomplish this, you will need take the world position, do some math to get it within the bounds of the SpriteRenderer, and then do some more math to find its position within the texture.

    This code below will clear a pixel from the texture of a Sprite when you click on it, if you attach this script to a GameObject with a SpriteRenderer. It should contain what you are looking for.

    using UnityEngine;
    
    public class ClickPosition : MonoBehaviour
    {
        private void OnMouseDown()
        {
            // example: get world position from click
            Vector3 worldPos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0.0f));
    
            SpriteRenderer renderer = GetComponent<SpriteRenderer>();
    
            // get pixel position in texture
            Vector2Int pixelPosition = GetPixelPositionInTexture(renderer, worldPos);
    
            // do what we want with that pixel to the texture
            // in this case, clear the pixel
            Texture2D tex = renderer.sprite.texture;
            tex.SetPixel(pixelPosition.x, pixelPosition.y, new Color());
            tex.Apply();
        }
    
        private Vector2Int GetPixelPositionInTexture(SpriteRenderer renderer, Vector3 worldPosition)
        {
            // bounds of the sprite renderer in the world
            Bounds bounds = renderer.bounds;
            // rect of the sprite within the texture
            Rect rect = renderer.sprite.rect;
    
            // get local position
            Vector2 localPos = worldPosition - bounds.min;
    
            // normalize the positon within the sprite
            Vector2 normalPos = new Vector2(localPos.x / bounds.size.x, localPos.y / bounds.size.y);
    
            // get the pixel positon within the sprite
            Vector2Int spritePixelPos = Vector2Int.FloorToInt(new Vector2(normalPos.x * rect.width, normalPos.y * rect.height));
    
            // get the pixel position within the texture
            Vector2Int texPixelPos = new Vector2Int(Mathf.FloorToInt(rect.x + spritePixelPos.x), Mathf.FloorToInt(rect.y + spritePixelPos.y));
    
            return texPixelPos;
        }
    }
    

    This code will not work if the camera or SpriteRenderer has been rotated or flipped. It will work with scaled GameObjects, and Sprites set to the Multiple sprite mode.