Yıkılabilir bir arazi yaratmak istiyorsanız, bunu Unity'de yaptığım gibi, sadece dünyanızın kenar bloklarına çarpıştırıcılar koymaktır. Yani, örneğin, bunu başarmak istersiniz:
Tüm bu yeşil bloklar bir çarpıştırıcı içeriyor ve geri kalanı yok. Bu hesaplamalara bir ton kazandırır. Bir bloğu yok ederseniz, bitişik bloklardaki çarpıştırıcıları kolayca etkinleştirebilirsiniz. Bir çarpıştırıcıyı etkinleştirmenin / devre dışı bırakmanın maliyetli olduğunu ve çok az yapılması gerektiğini unutmayın.
Böylece, Döşeme kaynağı şöyle görünür:
Standart bir gameobject, ama aynı zamanda poolable. Ayrıca, kutu toplayıcının varsayılan olarak devre dışı olarak ayarlandığını unutmayın. Yalnızca bir kenar döşemesi olduğunda etkinleştiririz.
Dünyanızı statik olarak yüklüyorsanız, karolarınızı havuzlamanıza gerek yoktur. Hepsini tek seferde yükleyebilir, kenardan mesafelerini hesaplayabilir ve gerekirse bir çarpıştırıcı uygulayabilirsiniz.
Dinamik olarak yüklüyorsanız, bir döşeme havuzu kullanmak en iyisidir. İşte benim yenileme döngümün düzenlenmiş bir örneği. Geçerli kamera görünümüne göre döşemeleri yükler:
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;
}
İdeal olarak, sahne arkasında biraz daha fazla şey olduğu için çok daha ayrıntılı bir yazı yazardım. Ancak, bu size yardımcı olabilir. Sorularınız varsa benimle iletişime geçmekten çekinmeyin.