วิธีรับไทล์ทั้งหมดจากไทล์แมป


13

ฉันได้ลองใช้TileMapระบบใหม่ใน Unity นิดหน่อยแล้วและฉันกำลังมองหาวิธีในการเข้าถึงไทล์เป็นรายการหรืออาเรย์สองมิติ แต่ฉันไม่พบสิ่งใดนอกจากGetTile(Vector3Int vector)ที่ส่งคืนไทล์เดียวเท่านั้น ... มีวิธีใดบ้าง เพื่อทำสิ่งนี้ ?

คำตอบ:


18

ที่จะได้รับอาเรย์ด้วยกระเบื้องทั้งหมดจากพื้นที่สี่เหลี่ยมของ 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.sizetilemap.ResizeBounds()

11

นี่เป็นอีกวิธีที่จะทำด้วย .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);
}

2

ในระหว่างการหาวิธีการรับไทล์ที่กำหนดเองทั้งหมดจาก 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)แต่ฉันไม่ได้ตรวจสอบ


คุณต้องจัดการกับส่วนต่อประสาน ITilemap ในสถานการณ์ใด ฉันไม่ได้พบเจอเลยระหว่างการทดสอบด้วยระบบ Tilemap ฉันได้รับส่วนประกอบ Tilemap ด้วยGetComponent<Tilemap>()เสมอ
ฟิลิปป์

~ Philipp ไม่สามารถบอกอะไรเกี่ยวกับอินเทอร์เฟซได้เพราะฉันทำงานกับ Component ด้วยเช่นกัน
Dmitry Tabakov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.