使用TileMap进行游戏地图开发

TileMap是一个强大的工具,它允许创建一个瓦片网格,可以在这个网格上渲染瓦片,而不是手动放置单个带有精灵的游戏对象。它内置了许多可能需要手动编写的功能,比如将坐标映射到地图上的特定单元格。使用TileMap的一个更酷的特点是,不需要自己编写编辑器来绘制瓦片!认为会选择避免这样做。但是有没有发现自己处于想要获取TileMap上所有绘制的瓦片的情况?可能会发现这并不像希望的那样明显!

TileMap上可以使用的功能

正如提到的,TileMap可以为做很多事情。特别是,发现自己想要获取所有与精灵关联的单元格,以及那个精灵实际上是什么。可以使用内置的方法GetSprite来实现这一点:

C# var cellPosition = new Vector3Int(x, y, 0); var sprite = tilemap.GetSprite(cellPosition);

足够简单。但是怎么知道要使用哪个坐标作为x和y呢?仅仅在x和y轴上从0到一个非常高的数字,然后用两个循环,希望这足够好?可以做得更好!TileMap类有一个方便的属性叫做cellBounds。这给一个整数矩形,定义了所有已经被修改的TileMap单元格的边界:

C# tilemap.cellBounds

如果发现自己在TileMap上做了很多编辑,可能需要擦除某些部分以专注于另一个区域。如果这是常见的,可能会从调用CompressBounds()中受益,以将其缩小到当前分配的单元格:

C# tilemap.CompressBounds()

有了所有这些,可以探讨如何将它们全部结合起来以获得所需要的!

小心TileMap.cellBounds和从零开始!

如果有敏锐的眼光,可能已经意识到想要使用两个循环来遍历TileMap上的cellBounds的x和y轴,以获取感兴趣的单元格。完全正确!但是这里有一些应该小心的事情!

这是一个容易犯的错误,因为通常这样编写循环:

C# for (int x = 0; x < bounds.max.x; x++) { for (int y = 0; y < bounds.max.y; y++) { // do stuff } }

但这有什么问题呢?起始值!需要小心在Unity中像2D空间这样工作。没有什么实际上保证瓦片是从TileMap上的零位置开始绘制的,并且只朝正方向移动。事实上,在游戏中,在正y轴上没有瓦片!所以一个简单的改变是确保不要搞砸,使用最小值作为起始点:

C# for (int x = bounds.min.x; x < bounds.max.x; x++) { for (int y = bounds.min.y; y < bounds.max.y; y++) { // do stuff } }

就这么简单!

C# public static class TileMapExtensionMethods { public static IEnumerable GetAllTiles(this Tilemap tilemap) { // Note: Optionally call tilemap.CompressBounds() some time prior to this var bounds = tilemap.cellBounds; // loop over the bounds (from min to max) on both axes for (int x = bounds.min.x; x < bounds.max.x; x++) { for (int y = bounds.min.y; y < bounds.max.y; y++) { var cellPosition = new Vector3Int(x, y, 0); // get the sprite and tile object at the specified location var sprite = tilemap.GetSprite(cellPosition); var tile = tilemap.GetTile(cellPosition); // This is a sanity check that I've included to ensure we're only // looking at populated tiles. You can change this up! if (tile == null && sprite == null) { continue; } // create a data-transfer-object to yield back var tileData = new TileData(x, y, sprite, tile); yield return tileData; } } } } public sealed class TileData { public TileData(int x, int y, Sprite sprite, TileBase tile) { X = x; Y = y; Sprite = sprite; Tile = tile; } public int X { get; } public int Y { get; } public Sprite Sprite { get; } public TileBase Tile { get; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485