You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何检测Sprite透明区域 仅在精灵可见部分生成预制体

Unity Sprite非透明区域方块填充实现方案

核心问题原因

之前的GetPixel方案失效,本质是四个逻辑错误:

  • 直接将世界坐标强转作为纹理像素坐标使用,未做坐标空间转换,采样位置完全不匹配
  • 未考虑Sprite的Pivot偏移、在源纹理/图集中的区域偏移、像素与单位的缩放比例
  • 直接判断像素不等于Color.clear的逻辑鲁棒性差,纹理压缩产生的噪点、半透明抗锯齿边缘都会导致判断错误
  • 未处理纹理未开启可读权限的情况

实现步骤

1. 前置资源配置

选中目标Sprite的源纹理,在Inspector面板做如下配置:

  • 将Texture Type设置为Sprite (2D and UI)
  • 勾选Read/Write Enabled选项
  • 纹理压缩格式选择无压缩格式,避免压缩导致alpha通道值偏差
  • 点击Apply保存配置

2. 核心实现代码

提前缓存所有公共参数,循环内完成坐标转换、越界判断、透明度校验三个核心逻辑:

// 提前缓存组件和Sprite参数,避免循环内重复获取
SpriteRenderer playerSr = player.GetComponent<SpriteRenderer>();
Sprite targetSprite = playerSr.sprite;
Texture2D targetTex = targetSprite.texture;
Rect spriteTextureRect = targetSprite.rect;
Vector2 spritePivot = targetSprite.pivot;
float ppu = targetSprite.pixelsPerUnit;

float newY = startVertical;
while (newY < endVertical)
{
    float newX = startHorizontal;
    while (newX < endHorizontal)
    {
        Vector3 spawnPos = new Vector3(newX, newY, 0);
        // 世界坐标转Sprite本地坐标
        Vector3 localPos = playerSr.transform.InverseTransformPoint(spawnPos);
        // 本地坐标转纹理像素坐标
        float px = localPos.x * ppu + spritePivot.x + spriteTextureRect.x;
        float py = localPos.y * ppu + spritePivot.y + spriteTextureRect.y;

        // 越界直接跳过
        if (px < 0 || px >= targetTex.width || py < 0 || py >= targetTex.height)
        {
            newX += fillerWidth + 0.1f;
            continue;
        }

        // 采样像素,通过alpha阈值判断是否为可见区域,阈值可根据需求调整
        Color pixel = targetTex.GetPixel((int)px, (int)py);
        if (pixel.a > 0.1f)
        {
            Instantiate(filler, spawnPos, Quaternion.identity);
        }

        newX += fillerWidth + 0.1f;
    }
    newY += fillerHeight + 0.1f;
}

3. 可选优化&兼容方案

  • 性能优化:不要在循环中逐次调用GetPixel,循环前先用GetPixels32()一次性读取整个Sprite区域的像素数据存入数组,循环中直接通过索引查询数组值,性能可提升数十倍
  • 图集兼容:上述坐标转换逻辑自动适配图集模式,sprite.rect已包含当前Sprite在图集纹理中的位置偏移,无需额外处理
  • 不可读纹理兼容:如果不想修改源纹理的导入配置,可在运行时创建可读纹理副本,实现代码如下:
Texture2D CreateReadableTextureCopy(Texture2D source)
{
    RenderTexture tempRT = RenderTexture.GetTemporary(source.width, source.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.sRGB);
    Graphics.Blit(source, tempRT);
    Texture2D readableCopy = new Texture2D(source.width, source.height);
    RenderTexture preRT = RenderTexture.active;
    RenderTexture.active = tempRT;
    readableCopy.ReadPixels(new Rect(0, 0, tempRT.width, tempRT.height), 0, 0);
    readableCopy.Apply();
    RenderTexture.active = preRT;
    RenderTexture.ReleaseTemporary(tempRT);
    return readableCopy;
}
  • 填充精度调整:如果需要每个方块精确对齐像素,可将fillerWidth、fillerHeight设置为1/ppu,间隔设为0即可

效果参考

  • 带透明区域的原始Sprite:原始带透明区域Sprite
  • 错误的全边界填充效果:错误全矩形填充效果
  • 目标非透明区域填充效果:目标填充效果

内容的提问来源于stack exchange,提问作者Martin Mbae

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 03:15:39