ฉันได้ลองใช้TileMap
ระบบใหม่ใน Unity นิดหน่อยแล้วและฉันกำลังมองหาวิธีในการเข้าถึงไทล์เป็นรายการหรืออาเรย์สองมิติ แต่ฉันไม่พบสิ่งใดนอกจากGetTile(Vector3Int vector)
ที่ส่งคืนไทล์เดียวเท่านั้น ... มีวิธีใดบ้าง เพื่อทำสิ่งนี้ ?
ฉันได้ลองใช้TileMap
ระบบใหม่ใน Unity นิดหน่อยแล้วและฉันกำลังมองหาวิธีในการเข้าถึงไทล์เป็นรายการหรืออาเรย์สองมิติ แต่ฉันไม่พบสิ่งใดนอกจากGetTile(Vector3Int vector)
ที่ส่งคืนไทล์เดียวเท่านั้น ... มีวิธีใดบ้าง เพื่อทำสิ่งนี้ ?
คำตอบ:
ที่จะได้รับอาเรย์ด้วยกระเบื้องทั้งหมดจากพื้นที่สี่เหลี่ยมของ tilemap tilemap.GetTilesBlock(BoundsInt bounds)
ของคุณใช้ คุณจะได้รับไพ่อาเรย์หนึ่งมิติดังนั้นคุณจำเป็นต้องรู้ด้วยตัวเองเมื่อไทล์แถวถัดไปเริ่มขึ้น เซลล์ว่างใด ๆ จะถูกแทนด้วยnull
ค่า
หากคุณต้องการทั้งหมดtilemap.cellBounds
กระเบื้องใช้ สิ่งนี้ทำให้คุณได้รับBoundsInt
วัตถุซึ่งครอบคลุมพื้นที่ที่ใช้ทั้งหมดของ tilemap นี่คือสคริปต์ตัวอย่างที่รับไทล์ทั้งหมดจาก Tilemap บนวัตถุเกมเดียวกันและแสดงรายการไพ่ด้วยพิกัดของพวกเขา:
using UnityEngine;
using UnityEngine.Tilemaps;
public class TileTest : MonoBehaviour {
void Start () {
Tilemap tilemap = GetComponent<Tilemap>();
BoundsInt bounds = tilemap.cellBounds;
TileBase[] allTiles = tilemap.GetTilesBlock(bounds);
for (int x = 0; x < bounds.size.x; x++) {
for (int y = 0; y < bounds.size.y; y++) {
TileBase tile = allTiles[x + y * bounds.size.x];
if (tile != null) {
Debug.Log("x:" + x + " y:" + y + " tile:" + tile.name);
} else {
Debug.Log("x:" + x + " y:" + y + " tile: (null)");
}
}
}
}
}
เกี่ยวกับขอบเขตและสาเหตุที่คุณอาจได้รับแผ่นกระเบื้องมากกว่าที่คุณคาดหวัง: ตามแนวคิดแล้ว Unity Tilemaps มีขนาดไม่ จำกัด การcellBounds
เติบโตตามที่ต้องการเมื่อคุณวาดภาพกระเบื้อง แต่พวกเขาจะไม่ย่ออีกถ้าคุณลบพวกเขา ดังนั้นเมื่อเกมของคุณมีขนาดแผนที่ที่กำหนดไว้อย่างดีคุณอาจได้รับความประหลาดใจถ้าคุณลื่นไถลในขณะที่แก้ไขแผนที่ มีสามวิธีในการแก้ไขปัญหานี้:
tilemap.CompressBounds()
เพื่อคืนขอบเขตให้กับกระเบื้องด้านนอกสุด (หวังว่าคุณจะจำได้เพื่อลบออก)bounds
ตัวเองกับวัตถุแทนที่จะอาศัยnew BoundsInt(origin, size)
cellBounds
tilemap.origin
และเป็นค่าที่ต้องการและโทรแล้วtilemap.size
tilemap.ResizeBounds()
นี่เป็นอีกวิธีที่จะทำด้วย .cellBounds.allPositionsWithin
public Tilemap tilemap;
public List<Vector3> tileWorldLocations;
// Use this for initialization
void Start () {
tileWorldLocations = new List<Vector3>();
foreach (var pos in tilemap.cellBounds.allPositionsWithin)
{
Vector3Int localPlace = new Vector3Int(pos.x, pos.y, pos.z);
Vector3 place = tilemap.CellToWorld(localPlace);
if (tilemap.HasTile(localPlace))
{
tileWorldLocations.Add(place);
}
}
print(tileWorldLocations);
}
ในระหว่างการหาวิธีการรับไทล์ที่กำหนดเองทั้งหมดจาก Tilemap และเนื่องจากITilemap
ยังไม่ได้GetTilesBlock
วิธีที่กล่าวถึงในคำตอบผมแนะนำให้เพิ่มวิธีการขยายเช่นนี้ (2D เท่านั้น):
public static class TilemapExtensions
{
public static T[] GetTiles<T>(this Tilemap tilemap) where T : TileBase
{
List<T> tiles = new List<T>();
for (int y = tilemap.origin.y; y < (tilemap.origin.y + tilemap.size.y); y++)
{
for (int x = tilemap.origin.x; x < (tilemap.origin.x + tilemap.size.x); x++)
{
T tile = tilemap.GetTile<T>(new Vector3Int(x, y, 0));
if (tile != null)
{
tiles.Add(tile);
}
}
}
return tiles.ToArray();
}
}
ในกรณีนี้ถ้าคุณมี TileRoad แบบกำหนดเองสืบทอดมาจาก Tile หรือ TileBase จากนั้นคุณจะได้รับไทล์ TileRoad ทั้งหมดที่มีการโทร:
TileBase[] = tilemap.GetTiles<RoadTile>();
สำหรับITilemapเราสามารถเปลี่ยนพารามิเตอร์(this Tilemap tilemap)
เป็น(this ITilemap tilemap)
แต่ฉันไม่ได้ตรวจสอบ
GetComponent<Tilemap>()
เสมอ