79 lines
3.0 KiB
C#
79 lines
3.0 KiB
C#
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// Чистые данные чанка — без MonoBehaviour, без Unity-объектов.
|
||
/// Легко сериализовать, передать в генератор, сохранить на диск.
|
||
/// </summary>
|
||
public class ChunkData
|
||
{
|
||
public const int SIZE = 16; // блоков по X и Z
|
||
public const int HEIGHT = 16; // блоков по Y
|
||
|
||
public readonly Vector3Int ChunkPos; // позиция чанка в чанковых координатах
|
||
|
||
// null = пустой блок, иначе blockId
|
||
private readonly string[,,] _blocks = new string[SIZE, HEIGHT, SIZE];
|
||
|
||
public bool IsDirty { get; private set; } = true; // нужен ли пересчёт меша
|
||
|
||
public ChunkData(Vector3Int chunkPos)
|
||
{
|
||
ChunkPos = chunkPos;
|
||
}
|
||
|
||
/// <summary>Получить blockId по локальным координатам. null = пусто.</summary>
|
||
public string GetBlock(int x, int y, int z)
|
||
{
|
||
if (!InBounds(x, y, z)) return null;
|
||
return _blocks[x, y, z];
|
||
}
|
||
|
||
public string GetBlock(Vector3Int local) => GetBlock(local.x, local.y, local.z);
|
||
|
||
/// <summary>Установить блок. null = удалить.</summary>
|
||
public void SetBlock(int x, int y, int z, string blockId)
|
||
{
|
||
if (!InBounds(x, y, z)) return;
|
||
_blocks[x, y, z] = blockId;
|
||
IsDirty = true;
|
||
}
|
||
|
||
public void SetBlock(Vector3Int local, string blockId) =>
|
||
SetBlock(local.x, local.y, local.z, blockId);
|
||
|
||
public void ClearDirty() => IsDirty = false;
|
||
|
||
public static bool InBounds(int x, int y, int z) =>
|
||
x >= 0 && x < SIZE &&
|
||
y >= 0 && y < HEIGHT &&
|
||
z >= 0 && z < SIZE;
|
||
|
||
/// <summary>
|
||
/// Перевод мировой позиции блока → позиция чанка (чанковые координаты).
|
||
/// </summary>
|
||
public static Vector3Int WorldToChunkPos(Vector3Int worldBlock) =>
|
||
new Vector3Int(
|
||
Mathf.FloorToInt((float)worldBlock.x / SIZE),
|
||
Mathf.FloorToInt((float)worldBlock.y / HEIGHT),
|
||
Mathf.FloorToInt((float)worldBlock.z / SIZE));
|
||
|
||
/// <summary>
|
||
/// Перевод мировой позиции блока → локальная позиция внутри чанка.
|
||
/// </summary>
|
||
public static Vector3Int WorldToLocal(Vector3Int worldBlock)
|
||
{
|
||
int x = worldBlock.x % SIZE;
|
||
int y = worldBlock.y % HEIGHT;
|
||
int z = worldBlock.z % SIZE;
|
||
// Обработка отрицательных координат
|
||
if (x < 0) x += SIZE;
|
||
if (y < 0) y += HEIGHT;
|
||
if (z < 0) z += SIZE;
|
||
return new Vector3Int(x, y, z);
|
||
}
|
||
|
||
/// <summary>Позиция чанка → мировая позиция его нижнего-левого угла.</summary>
|
||
public static Vector3Int ChunkToWorld(Vector3Int chunkPos) =>
|
||
new Vector3Int(chunkPos.x * SIZE, chunkPos.y * HEIGHT, chunkPos.z * SIZE);
|
||
}
|