Jika Anda ingin membuat medan yang dapat dirusak, cara saya melakukan ini di Unity, adalah dengan hanya mengatur colliders di blok tepi dunia Anda. Jadi misalnya, inilah yang ingin Anda capai:
Semua blok hijau itu mengandung collider, dan sisanya tidak. Itu menghemat satu ton pada perhitungan. Jika Anda menghancurkan blok, Anda dapat mengaktifkan colliders pada blok yang berdekatan dengan mudah. Perlu diingat bahwa mengaktifkan / menonaktifkan collider adalah mahal dan harus dilakukan hemat.
Jadi, sumber daya Tile terlihat seperti ini:
Ini adalah objek game standar, tetapi juga bisa dikumpulkan. Perhatikan juga bahwa kotak collider diatur untuk dinonaktifkan secara default. Kami hanya akan mengaktifkan jika itu adalah ubin tepi.
Jika Anda memuat dunia Anda secara statis, tidak perlu menyatukan ubin Anda. Anda bisa memuat semuanya dalam satu tembakan, menghitung jaraknya dari tepi, dan menerapkan collider jika diperlukan.
Jika Anda memuat secara dinamis, yang terbaik adalah menggunakan kolam ubin. Ini adalah contoh loop refresh saya yang diedit. Ini memuat ubin berdasarkan tampilan kamera saat ini:
public void Refresh(Rect view)
{
//Each Tile in the world uses 1 Unity Unit
//Based on the passed in Rect, we calc the start and end X/Y values of the tiles presently on screen
int startx = view.x < 0 ? (int)(view.x + (-view.x % (1)) - 1) : (int)(view.x - (view.x % (1)));
int starty = view.y < 0 ? (int)(view.y + (-view.y % (1)) - 1) : (int)(view.y - (view.y % (1)));
int endx = startx + (int)(view.width);
int endy = starty - (int)(view.height);
int width = endx - startx;
int height = starty - endy;
//Create a disposable hashset to store the tiles that are currently in view
HashSet<Tile> InCurrentView = new HashSet<Tile>();
//Loop through all the visible tiles
for (int i = startx; i <= endx; i += 1)
{
for (int j = starty; j >= endy; j -= 1)
{
int x = i - startx;
int y = starty - j;
if (j > 0 && j < Height)
{
//Get Tile (I wrap my world, that is why I have this mod here)
Tile tile = Blocks[Helper.mod(i, Width), j];
//Add tile to the current view
InCurrentView.Add(tile);
//Load tile if needed
if (!tile.Blank)
{
if (!LoadedTiles.Contains(tile))
{
if (TilePool.AvailableCount > 0)
{
//Grab a tile from the pool
Pool<PoolableGameObject>.Node node = TilePool.Get();
//Disable the collider if we are not at the edge
if (tile.EdgeDistance != 1)
node.Item.GO.GetComponent<BoxCollider2D>().enabled = false;
//Update tile rendering details
node.Item.Set(tile, new Vector2(i, j), DirtSprites[tile.TextureID], tile.Collidable, tile.Blank);
tile.PoolableGameObject = node;
node.Item.Refresh(tile);
//Tile is now loaded, add to LoadedTiles hashset
LoadedTiles.Add(tile);
//if Tile is edge block, then we enable the collider
if (tile.Collidable && tile.EdgeDistance == 1)
node.Item.GO.GetComponent<BoxCollider2D>().enabled = true;
}
}
}
}
}
}
//Get a list of tiles that are no longer in the view
HashSet<Tile> ToRemove = new HashSet<Tile>();
foreach (Tile tile in LoadedTiles)
{
if (!InCurrentView.Contains(tile))
{
ToRemove.Add(tile);
}
}
//Return these tiles to the Pool
//this would be the simplest form of cleanup -- Ideally you would do this based on the distance of the tile from the viewport
foreach (Tile tile in ToRemove)
{
LoadedTiles.Remove(tile);
tile.PoolableGameObject.Item.GO.GetComponent<BoxCollider2D>().enabled = false;
tile.PoolableGameObject.Item.GO.transform.position = new Vector2(Int32.MinValue, Int32.MinValue);
TilePool.Return(tile.PoolableGameObject);
}
LastView = view;
}
Idealnya, saya akan menulis posting yang jauh lebih rinci, karena ada sedikit lebih banyak terjadi di belakang layar. Namun, ini dapat membantu Anda. Jika ada pertanyaan, jangan ragu untuk bertanya atau menghubungi saya.