Skip to content

Tilemap

更新: 8/8/2025 字数: 0 字 时长: 0 分钟

Tilemap(瓦片地图)是 Unity 中用于创建 2D 关卡的强大工具,它允许你使用小的、可重复使用的 Sprite(称为 Tile)来构建游戏世界。

Tilemap 系统概述

Tilemap 就像是一个画布,你可以使用自定义的笔刷,自由地进行绘制。Tilemap 系统使得创建复杂的 2D 场景变得简单高效。

Unity 中的 Tilemap 系统主要由5个部分组成:

  1. Sprite 精灵:2D 中纹理的容器。
  2. Tile 瓦片:包含一个精灵,以及颜色和碰撞体类型。
  3. Palette 调色板:保存 Tile,将它们绘制到网格上。
  4. Brush 笔刷:用于将预制的笔刷绘制到画布上。
  5. Tilemap 瓦片地图:画布。

使用 Tile Palette 进行绘制

在 Unity 中,Tilemap 的绘制可以分为以下几个步骤:

  1. 创建调色板(Palette)
    通过菜单栏选择 Window > 2D > Tile Palette 打开 Tile Palette 窗口。如果还没有调色板,Active Palette 会显示 No Valid Palette,点击 Create New Palette 创建一个新的调色板。创建时可设置 Grid Type(网格类型),常用类型有:

    • Rectangular:矩形瓦片
    • Hexagonal:六边形瓦片
    • Isometric:等距瓦片
    • Isometric Z as Y:等距瓦片,Z 轴作为 Y 轴
  2. 添加 Tile 到调色板
    将准备好的 Sprite 拖拽到调色板窗口中,即可自动生成对应的 Tile。如需调整调色板内容,可点击右侧的 Toggle Tile Palette Edit 进入编辑模式。

  3. 创建 Tilemap 画布
    在 Hierarchy 面板中右键,选择 2D Object > Tilemap,根据需要选择合适的 Tilemap 类型。Tilemap 就是我们实际绘制 2D 场景的画布。

  4. 在 Tilemap 上绘制
    在 Tile Palette 窗口点击 Toggle Tile Palette Edit 进入编辑模式,使用吸色笔选择需要的 Tile,然后在 Scene 视图中点击或拖动鼠标,即可将 Tile 绘制到 Tilemap 上。

Tile Palette 绘制工具

TilePalette工具 Tile Palette 面板上方提供了多种绘制工具:

  • 选择工具
  • 移动工具(可移动 Tile)
  • 笔刷工具
  • 框填工具
  • 吸色笔
  • 橡皮擦
  • 填充工具

注意事项:

  • Isometric Z as Y 调色板中,如果 Tile 在调色板中未对齐网格中心,可勾选下方 Can Change Z Position,并在绘制时用 +、- 键调整 Z 轴位置。但在做具有伪 Z 轴的 2D 游戏时,通常还是使用 Isometric 调色板。Sp
  • 精灵纹理的轴心点会影响 Tile 的显示效果。
  • 使用等距瓦片时,Unity 默认用 z 轴决定前后关系,但等距瓦片游戏通常不需要 z 轴。为避免遮挡问题,可按如下方式调整排序:
    • 进入 Edit -> Project Settings -> Graphics -> Transparency Sort Mode,将其设置为 Custom Axis,并将 Transparency Sort Axis 设置为 (0, 1, -0.26)。
    • Tilemap Renderer 组件的 Mode 设置为 Individual

Grid 组件

所有的 Tilemap 都需要一个 Grid 组件来定义网格的布局。如果是首次创建 Tilemap, Unity 会自动生成一个携带 Grid 组件的游戏对象(通常就叫做 Grid),就如同 UI 元素与 Canvas 的关系一样。

Grid 组件允许你设置与网格排列相关的属性:

属性名说明
Cell Size网格单元的大小。
Cell Gap网格单元之间的间距。
Cell Layout网格的布局方式,如矩形、六边形等。Create Tile Palette 时不同类型的 Tilemap 的区别其实就在这里。
Cell Swizzle将单元格坐标重新排序为选择类型。通常保持默认即可。

如果美术资源太大或太小,可以通过修改 Cell Size 和图集的 Pixels Per Unit 来调整大小。

Tilemap 组件

Tilemap 组件上的参数很少有情况需要去修改它,其包含了一些全局属性:

属性名说明
Animation Frame Rate瓦片动画播放速率。
Color色调。
Tile Anchor瓦片的锚点偏移。
Orientation瓦片地图上瓦片的朝向。相当于 2D 平面使用的是 Unity 中的哪两个轴。

Tilemap Renderer 组件

Tilemap Renderer 组件挂载在 Tilemap 上,负责渲染瓦片内容。主要属性包括:

属性名说明
Sort Order所选瓦片在地图上的排序方向。可以视作设置画布原点。
Mode瓦片渲染模式。Chunk 会将精灵进行批处理渲染,Individual 则会逐个渲染。
Detect Chunk Culling渲染器渲染边界。Auto 模式下只会渲染摄像机内瓦片。
Material瓦片渲染使用的材质。默认使用 Sprites-Default 材质不受光照影响。
Sorting Layer瓦片渲染的排序层级。
Order in Layer瓦片渲染的层级顺序。

添加碰撞器

为 Tilemap 添加碰撞器非常方便,只需要再 Tilemap 上添加一个 Tilemap Collider 2D 组件即可。该组件会自动为每个 Tile 生成碰撞器。

可以通过 Composite Collider 2D 组件来优化碰撞器的生成。该组件会将所有 Tile 的碰撞器合并为一个单一的碰撞器,从而提高性能。由于挂载 Composite Collider 2D 组件时还会自动添加 Rigidbody 2D 组件,如果不需要物理效果,可以将 Rigidbody 2DBody Type 设置为 Static

此外还可以在 Inspector 中修改 TileCollider Type

瓦片碰撞器类型说明
None不生产碰撞器。
Sprite使用精灵的形状作为碰撞器(默认)。
Grid将严格按照该瓦片所在的网格单元 (Grid Cell) 的形状来生成。

TIP

在等距瓦片游戏中,墙壁等静态物体通常设为 Grid,地面通常设为 None

如果需要做一些特殊的功能(例如使用平台效应器),Tilemap 碰撞器可能无法满足需求。此时可以单独创建一个空物体并为其添加碰撞器组件(如 Box Collider 2DPolygon Collider 2D)。对于复杂的逻辑不用过度依赖 Tilemap 碰撞器。

Tilemap 渲染顺序

Tilemap 中 Sprite 渲染优先级:

  1. Order in Layer:在同一层级中,较大的值会被渲染在较小的值之上。
  2. Sorting Layer:不同的排序层级会影响渲染顺序。
  3. Z Position:在等距瓦片中,Z 轴位置会影响渲染顺序,较小的 Z 值会被渲染在较大的 Z 值之上。
角色与 NPC 的轴心点调整

在等距瓦片中,默认创建的人物或者 NPC 对象可能会出现半个身子被地面遮挡,看起来被埋在地里一样的情况。这就是渲染顺序的问题,根据角色图片中心点排序容易会导致渲染顺序的错误。

解决方案:

  • 使用 Sprite Editor 将角色的轴心点调整到脚底下方。然后修改 Sprite RendererSprite Sort Point 属性为 Pivot,这样就可以确保角色正确地站在地面上。
  • 修改 Order In Layer 属性,使其大于地板排序层级。

此外,为了更方便地处理运动逻辑,通常都会把需要站立在地面上的物体的轴心点设置在底部。

对于设置渲染层级还无法解决问题,可能是 Tilemap RendererMode 设置为 Chunk,此时会将 Tilemap 划分为多个块进行渲染。可以尝试将其改为 Individual 模式,这样每个 Tile 都会单独渲染,可能会解决一些渲染顺序问题。

Tilemap 的局限

  • Tilemap 制作地形很方便,但只能在一个格子中心绘制 Tile,无法在格子之间绘制。
  • 对于需要有逻辑交互的地形不方便制作(如平台效应器)。
  • Tilemap 主要用于静态场景,动态物体(如角色)需要单独处理。

常用 API

可以通过 Tilemap 组件的 API 来操作 Tilemap,进行增删改查等,例如:

csharp
// 获取 Tile
TileBase tile = tilemap.GetTile(tilePosition);

// 设置 Tile
tilemap.SetTile(tilePosition, newTile);

// 清除 Tile
tilemap.SetTile(tilePosition, null);

// 批量设置 Tiles
tilemap.SetTiles(tilePositionArray, tileArray);

// 批量替换 Tiles
map.SwapTile(oldTile, newTile);

其中,TileBase 是所有 Tile 的基类;tilePosition 类型为 Vector3Int

此外,还可以使用 tilemap.WorldToCell(Vector3 worldPos) 方法将世界坐标转换为 Tilemap 的格子坐标,例如:

csharp
// 获取鼠标在屏幕上的位置
Vector2 mousePosition = Input.mousePosition;
// 将屏幕坐标转换为世界坐标
Vector3 worldPosition = mainCamera.ScreenToWorldPoint(
   new Vector3(mousePosition.x, mousePosition.y, mainCamera.nearClipPlane));
// 将世界坐标转换为 Tilemap 的单元格坐标
Vector3Int cellPosition = tilemap.WorldToCell(worldPosition);

2D Tilemap Extras 扩展包

2D Tilemap Extras 是 Unity 官方推出的一个免费扩展包,旨在增强内置 2D Tilemap 系统的功能。 它将过去社区中广受欢迎的自定义脚本(来自旧的 2d-extras)进行了优化和整合,变成了官方支持的、更稳定、更易于使用的工具集。

安装方式:

  1. 打开 Unity Package Manager。
  2. 点击左上角的 + 按钮,选择 Add package from git URL...。
  3. 输入 com.unity.2d.tilemap.extras,点击 Add。

在 Project 窗口可找到 2D Tilemap Extras 扩展包带来的 Tiles,在 Tile Palette 中可以找到新增的笔刷。

Tile

Rule Tile

Rule Tile 是一种“智能”瓦片,它能够根据自身周围的邻居瓦片,自动从一个列表中选择并显示正确的 Sprite

它主要解决了在拼接地图时,不同区域(如草地、墙壁)之间需要大量过渡瓦片(如边角、边缘)的问题。通过预设规则,Rule Tile 可以将这个繁琐的过程完全自动化,极大提升关卡搭建的效率和美观度。

Rule Tile 核心属性:

属性 (Property)功能说明 (Function)
Default Sprite默认显示的精灵。当没有一条规则被满足时,会显示此精灵。
Default GameObject默认生成的游戏对象。
Default Collider默认的碰撞器类型 (None, Sprite, Grid)。
Number of Tiling Rules显示你当前已经创建了多少条平铺规则 (Tiling Rules),只读不用修改。
Tiling Rules平铺规则列表。这是 Rule Tile 的核心,你可以在这里定义所有的匹配规则和对应的输出。

Tiling Rules 规则详解:

每个规则都由“匹配条件”和“输出结果”两部分组成。

规则属性 (Rule Property)功能说明 (Function)
匹配网格 (3x3 Grid)定义匹配条件的核心。中心格子代表当前瓦片,周围8个格子代表其邻居。点击格子可以切换三种状态:箭头 (必须是同类)、叉号 (必须不是同类) 和 空 (不关心)。
Rule Transform规则变换。用于处理旋转和镜像,可以极大减少规则的数量。
Sprite当此条规则匹配成功时,显示的精灵。
GameObject匹配成功时,实例化的预制体。可以用来创建可交互的对象。
Collider Type匹配成功时,瓦片的碰撞器类型。
Output输出类型。通常为 Single(单一输出),也可设为 Random(从精灵列表中随机选一个)或 Animation(播放序列帧动画)。

Rule Tile 默认是 Rectangular 网格类型, Create 窗口还具有其他类型的瓦片,如 Hexagonal Rule TileIsometric Rule Tile

Animated Tile

Animated Tile (动画瓦片) 是一种可以随时间播放序列帧动画的瓦片。它让你的 2D 世界充满生机,非常适合用来制作流动的岩浆、闪烁的宝石、燃烧的火焰或动态的背景元素。

你需要提供一组静态的 Sprite 图片,Animated Tile 会按照你设定的速度循环播放这些图片,从而形成动画效果。

Animated Tile 核心属性:

属性 (Property)功能说明 (Function)
Number of Animated Sprites动画包含的总帧数,只读不用修改。
Animated Sprites存放动画序列帧的列表。你需要按照播放顺序将 Sprite 拖拽到这里。
Minimum Speed动画播放的最小速度,单位是“帧/秒”。
Maximum Speed动画播放的最大速度,单位是“帧/秒”。每个瓦片的实际播放速度会是这个范围内的随机值。
Animation Start Time动画开始播放的时间。Sync 表示所有瓦片同步播放,Random 表示每个瓦片随机一个起始时间。
Collider Type该瓦片的碰撞器类型 (None, Sprite, Grid)。

Rule Override Tile

Rule Override Tile (规则覆盖瓦片) 是一种高级瓦片,它本身不包含任何平铺规则。相反,它会继承一个已有的 Rule Tile 的所有规则,并允许你只针对性地覆盖 (Override) 其中一条或几条规则的输出结果。

Rule Override Tile 核心属性:

属性 (Property)功能说明 (Function)
Tile指定要继承规则的“父” Rule Tile。这是建立继承关系的关键。
Overrides一个列表,包含了所有你想要覆盖的规则。每个列表项都定义了一个“原始输出”到“新输出”的映射关系。

Advanced Rule Override Tile

Advanced Rule Override Tile (高级规则覆盖瓦片) 是 Rule Override Tile 的直接超集。它继承了后者的所有功能——即继承一个基础 Rule Tile 的规则并覆盖其输出的 Sprite——同时,它还额外提供了覆盖 GameObject (预制体) 和 Collider Type (碰撞器类型) 的能力。

核心功能扩展:

覆盖属性 (Override Property)功能说明 (Function)
Override Sprite (同 Rule Override Tile)勾选此项,可以提供一个新的 Sprite 来替换原始规则的 Sprite 输出。
Override GameObject (新增)勾选此项,可以提供一个新的 GameObject 预制体来替换原始规则的 GameObject 输出。
Override Collider (新增)勾选此项,可以选择一个新的 Collider Type 来替换原始规则的碰撞器类型。

Brushes

GameObject Brush

GameObject Brush (游戏对象笔刷) 允许你直接将游戏对象 (GameObjects),通常是预制体 (Prefabs),“绘制”或“盖章”到场景的网格上。

笔刷核心属性:

属性 (Property)功能说明 (Function)
GameObject绘制的对象。
Offset绘制时的对象的偏移量。
Scale绘制时对象的缩放比例。
Orientation绘制时对象的旋转角度。
Size可同时绘制的对象数量。

Group Brush

可以设置参数,当点击一个瓦片时,会自动取出一个范围内的瓦片。

核心属性:

属性 (Property)功能说明 (Function)
Gap遇到几个空白瓦片时,停止继续探测尝试选取。
Limit一个方向上最多可以选取的瓦片数量(同一个轴的正负算作两个方向)。

Random Brush

可以随机绘制瓦片。

核心属性:

属性 (Property)功能说明 (Function)
Tile Set Size瓦片集大小。
Number of Tiles瓦片数量。

Line Brush

选择一个瓦片绘制一条直线。

核心属性:

属性 (Property)功能说明 (Function)
Line Start Active使用上一个起点。
Fill Gaps通过绘制更多瓦片使线段更饱满。
Line Start线段起点坐标。

Custom Rule Tile Script

Custom Rule Tile Script (自定义规则瓦片脚本) 不是一个可以直接使用的瓦片,而是一个 C# 脚本模板。通过编辑这个脚本,你可以创建出拥有全新匹配规则的、完全自定义的 Rule Tile。

Custom Rule Tile Script 模版示例
csharp
[CreateAssetMenu]
public class CoastlineRuleTile : RuleTile<CoastlineRuleTile.Neighbor> 
{
    // 添加一个公开的列表,用于在 Inspector 中指定哪些瓦片算作“水”
   public List<TileBase> waterTiles;

   public class Neighbor : RuleTile.TilingRule.Neighbor 
   {
      // 定义一个新规则 "IsWater"
      public const int IsWater = 3; 
   }

   public override bool RuleMatch(int neighbor, TileBase tile) 
   {
      switch (neighbor) 
      {
         // 当规则是 IsWater 时,检查邻居瓦片是否存在于我们的 waterTiles 列表中
         case Neighbor.IsWater: return waterTiles.Contains(tile);
      }
      return base.RuleMatch(neighbor, tile);
   }
}