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

Unity等距Tilemap多精灵排序失效问题(PPU/锚点一致仍异常)

Unity等距Tilemap排序冲突解决方案

问题背景

精灵资源规格

  • 尺寸:所有精灵均为500x500像素
  • 像素每单位(PPU):均设为512
  • 锚点(Pivot):统一自定义锚点(250, 375)(对应立方体顶部菱形的底部中心)
  • 几何形状:精灵形状和元数据完全一致,仅颜色和文件名不同

问题现象

  • 当三个插槽使用同一精灵(如仅草地)时,区块渲染正常,Y轴排序符合预期。
  • 一旦使用不同文件(Grass.png、Sand.png、Water.png),排序完全失效,背景Tile频繁覆盖前景Tile,出现图层混乱。

生成器代码

using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEngine.Rendering;
using System.Collections.Generic;

public class WorldGenerator : MonoBehaviour
{
    [Header("Sprites")]
    public Sprite waterSprite;
    public Sprite sandSprite;
    public Sprite grassSprite;

    [Header("Settings")]
    public int chunkSize = 16;
    
    private Dictionary<string, Tile> tileCache = new Dictionary<string, Tile>();

    void Start()
    {
        // Setting up global sorting for isometry
        GraphicsSettings.transparencySortMode = TransparencySortMode.CustomAxis;
        GraphicsSettings.transparencySortAxis = new Vector3(0, 1, -1);

        GenerateSingleChunk();
    }

    void GenerateSingleChunk()
    {
        GameObject oldGrid = GameObject.Find("IsoGrid");
        if (oldGrid) DestroyImmediate(oldGrid);

        GameObject gridObj = new GameObject("IsoGrid");
        Grid grid = gridObj.AddComponent<Grid>();
        grid.cellLayout = GridLayout.CellLayout.Isometric;
        
        // Size for 500px sprites with 512 PPU
        float sw = 500f / 512f;
        grid.cellSize = new Vector3(sw, sw * 0.5f, 1f);

        GameObject chunkObj = new GameObject("Chunk_Main");
        chunkObj.transform.SetParent(gridObj.transform);
        
        Tilemap tilemap = chunkObj.AddComponent<Tilemap>();
        TilemapRenderer tr = chunkObj.AddComponent<TilemapRenderer>();

        tilemap.tileAnchor = Vector3.zero; 
        tr.mode = TilemapRenderer.Mode.Individual; 
        tr.sortOrder = TilemapRenderer.SortOrder.TopRight;

        for (int x = 0; x < chunkSize; x++)
        {
            for (int y = 0; y < chunkSize; y++)
            {
                tilemap.SetTile(new Vector3Int(x, y, 0), GetRandomTile());
            }
        }
    }

    Tile GetRandomTile()
    {
        float r = Random.value;
        if (r < 0.33f) return GetCachedTile("Water", waterSprite);
        if (r < 0.66f) return GetCachedTile("Sand", sandSprite);
        return GetCachedTile("Grass", grassSprite);
    }

    Tile GetCachedTile(string id, Sprite s)
    {
        if (!tileCache.ContainsKey(id))
        {
            Tile t = ScriptableObject.CreateInstance<Tile>();
            t.sprite = s;
            tileCache[id] = t;
        }
        return tileCache[id];
    }
}

问题截图

图层混乱效果1
图层混乱效果2

可行解决方案

1. 统一Tile的共享材质

不同Sprite导入时自动生成的材质可能存在渲染队列或参数差异,导致排序计算异常。

  • 手动创建一个透明材质(渲染队列设为Transparent),在Inspector中赋值给脚本的sharedTileMaterial变量。
  • 修改GetCachedTile方法,给所有Tile绑定该共享材质:
public Material sharedTileMaterial; // 在Inspector赋值

Tile GetCachedTile(string id, Sprite s)
{
    if (!tileCache.ContainsKey(id))
    {
        Tile t = ScriptableObject.CreateInstance<Tile>();
        t.sprite = s;
        t.material = sharedTileMaterial; // 统一材质
        tileCache[id] = t;
    }
    return tileCache[id];
}

2. 切换Tilemap渲染模式为Chunk

当前Individual模式会让每个Tile单独渲染,不同Sprite可能触发不同的排序批次。改为Chunk模式后,Tilemap会合并Tile渲染,统一计算排序:

tr.mode = TilemapRenderer.Mode.Chunk;

3. 调整透明排序轴与添加Sorting Group

  • 尝试调整全局透明排序轴为等距视角常用的深度计算方向:
GraphicsSettings.transparencySortAxis = new Vector3(1, 1, 0);
  • 给Chunk_Main GameObject添加SortingGroup组件,强制统一组内元素的排序规则,避免不同Sprite的渲染批次干扰。

4. 给不同类型Tile设置Z轴偏移

通过微小的Z轴偏移强制指定绘制顺序,保证草地>沙地>水域:

Tile GetCachedTile(string id, Sprite s)
{
    if (!tileCache.ContainsKey(id))
    {
        Tile t = ScriptableObject.CreateInstance<Tile>();
        t.sprite = s;
        // 根据Tile类型设置Z偏移,值越大越晚绘制(显示在上方)
        float zOffset = id switch
        {
            "Water" => -0.01f,
            "Sand" => 0f,
            "Grass" => 0.01f,
            _ => 0f
        };
        t.transform = Matrix4x4.Translate(new Vector3(0, 0, zOffset));
        tileCache[id] = t;
    }
    return tileCache[id];
}

5. 统一Sprite导入设置

打开所有Sprite的Import Settings,确保以下参数完全一致:

  • Mesh Type(建议设为Full Rect)
  • Extrude Edges
  • Filter Mode
  • Wrap Mode
    避免Unity为不同Sprite生成不同网格数据,导致排序计算异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 16:05:07