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

Unity TileMap Shader瓦片接缝灰线问题求助

Hey there! Let's tackle those annoying tile seam lines you're dealing with. You’re absolutely right to suspect floating-point precision issues—this is a super common gotcha with tile mapping shaders, especially when sampling from a spritesheet and doing UV calculations that can drift slightly due to floating-point errors. Let’s break down the fixes step by step:

1. Fix UV & Tile Index Precision

Your current index calculation and UV mod operations are prone to tiny precision errors that can push sampling just over a tile boundary. Here’s how to tighten that up:

  • Replace the % operator with frac() for more reliable fractional UV extraction—frac() is designed exactly for getting the decimal part of a float, which avoids edge-case errors with mod.
  • Add a tiny offset when converting UV to integer tile coordinates to prevent floor() from rounding down incorrectly due to precision drift.
  • Clamp your tile coordinates to avoid index out-of-bounds issues (which can cause random wrong tiles/seams).

2. Add Texture Padding (The Most Reliable Fix)

Most tile seam gray lines come from texture filtering (like linear filtering) sampling pixels from adjacent tiles in your spritesheet. To fix this, add 1-pixel padding around each tile in your _DiffuseTex spritesheet, matching the edge color of the tile. Then adjust your shader to sample only the inner tile area, skipping the padding.

Modified Shader Fragment Code

Here’s the updated frag function incorporating these fixes:

fixed4 frag (v2f i) : SV_Target {
    float mapSizeModif = 1.0f / _MapWidth;
    float worldSizeModif = 1.0f / _WorldWidth;
    float maskMapSizeModif = 1.0f / _MaskMapWidth;

    float lightness = 1.0f;

    // Fix tile index precision with offset + clamping
    float2 worldUV = i.uv * _WorldWidth;
    uint x = (uint)clamp(floor(worldUV.x + 0.0001f), 0, _WorldWidth - 1);
    uint y = (uint)clamp(floor(worldUV.y + 0.0001f), 0, _WorldWidth - 1);
    uint index = x + y * _WorldWidth;

    // Use frac() for clean local tile UV instead of mod
    float2 tileLocalUV = frac(worldUV) * worldSizeModif;

    uint id = (uint)_allIDs[index];

    // Base UV position for the tile in the spritesheet
    float2 tileBaseUV = float2(
        mapSizeModif * (id % _MapWidth),
        mapSizeModif * floor(((float)id)/_MapWidth)
    );

    // Adjust for texture padding (tweak values to match your spritesheet)
    // Example: 1px padding on a 256x256 spritesheet = 1/256 = 0.00390625
    float tilePadding = 0.00390625; 
    float tileScale = (mapSizeModif - 2 * tilePadding) / mapSizeModif;
    tileLocalUV = tileLocalUV * tileScale + tilePadding;

    // Combine base and local UVs for final sampling
    float2 finalUV = tileBaseUV + tileLocalUV;

    fixed4 col = tex2D(_DiffuseTex, finalUV);
    col *= _GlobalLumosity;
    col *= _GlobalHue;
    col.a = lightness;

    return col;
}

Extra Quick Checks

  • Set your _DiffuseTex wrap mode to Clamp in the Unity inspector—this prevents accidental sampling of distant tiles if UVs drift slightly.
  • If you can’t add padding right away, switch the texture’s filter mode to Point (no filter)—this eliminates filtering-induced seams but makes tiles look pixelated (use this as a temporary test to confirm the issue is filtering-related).

Key Notes

  • The tilePadding value depends on your spritesheet size: for a 512x512 sheet, 1px padding is 1/512 = 0.001953125. Make this a Shader property if you want to adjust it without re-compiling.
  • The precision fixes alone might reduce seams, but combining them with texture padding will fully resolve the issue in most cases.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:18:35