Files
ProjectMD/Assets/Scripts/Underground/ChunkCoord.cs
Dal4segno 59246a67bd 지하 최적화
블록 프리팹 단위 -> 블록 청크 단위 스폰
기타 건설, 조준 관련 사이드이펙트 버그 수정
2026-01-21 21:34:05 +09:00

216 lines
6.2 KiB
C#

using UnityEngine;
/// <summary>
/// Utility struct for chunk coordinate conversions.
/// Handles conversions between world, grid, chunk, and local block coordinates.
/// </summary>
public struct ChunkCoord
{
public const int CHUNK_SIZE = 4;
/// <summary>
/// Chunk position in chunk coordinates (not world or grid)
/// </summary>
public Vector3Int chunkPos;
public ChunkCoord(Vector3Int pos)
{
chunkPos = pos;
}
public ChunkCoord(int x, int y, int z)
{
chunkPos = new Vector3Int(x, y, z);
}
/// <summary>
/// Get the grid position of the chunk's origin (corner with smallest coordinates)
/// </summary>
public Vector3Int GridOrigin => new Vector3Int(
chunkPos.x * CHUNK_SIZE,
chunkPos.y * CHUNK_SIZE,
chunkPos.z * CHUNK_SIZE
);
/// <summary>
/// Get world position of chunk origin using BuildManager's grid system
/// </summary>
public Vector3 WorldOrigin
{
get
{
if (BuildManager.Instance != null)
{
return BuildManager.Instance.GridToWorld(GridOrigin);
}
// Fallback if BuildManager not available
return new Vector3(
GridOrigin.x + 0.5f,
GridOrigin.y + 0.5f,
GridOrigin.z + 0.5f
);
}
}
/// <summary>
/// Convert grid coordinates to chunk coordinates
/// </summary>
public static ChunkCoord FromGridPos(Vector3Int gridPos)
{
return new ChunkCoord(
Mathf.FloorToInt((float)gridPos.x / CHUNK_SIZE),
Mathf.FloorToInt((float)gridPos.y / CHUNK_SIZE),
Mathf.FloorToInt((float)gridPos.z / CHUNK_SIZE)
);
}
/// <summary>
/// Convert world position to chunk coordinates
/// </summary>
public static ChunkCoord FromWorldPos(Vector3 worldPos)
{
Vector3Int gridPos;
if (BuildManager.Instance != null)
{
gridPos = BuildManager.Instance.WorldToGrid3D(worldPos);
}
else
{
// Fallback
gridPos = new Vector3Int(
Mathf.RoundToInt(worldPos.x - 0.5f),
Mathf.RoundToInt(worldPos.y - 0.5f),
Mathf.RoundToInt(worldPos.z - 0.5f)
);
}
return FromGridPos(gridPos);
}
/// <summary>
/// Get local block coordinates within chunk from grid position
/// </summary>
public static Vector3Int GridToLocal(Vector3Int gridPos)
{
// Use modulo to get local position, handling negative coords
int x = ((gridPos.x % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE;
int y = ((gridPos.y % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE;
int z = ((gridPos.z % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE;
return new Vector3Int(x, y, z);
}
/// <summary>
/// Convert local block coordinates to grid position
/// </summary>
public Vector3Int LocalToGrid(Vector3Int localPos)
{
return GridOrigin + localPos;
}
/// <summary>
/// Convert local block coordinates to world position
/// </summary>
public Vector3 LocalToWorld(Vector3Int localPos)
{
Vector3Int gridPos = LocalToGrid(localPos);
if (BuildManager.Instance != null)
{
return BuildManager.Instance.GridToWorld(gridPos);
}
return new Vector3(gridPos.x + 0.5f, gridPos.y + 0.5f, gridPos.z + 0.5f);
}
/// <summary>
/// Convert local index to local 3D coordinates
/// </summary>
public static Vector3Int IndexToLocal(int index)
{
int x = index % CHUNK_SIZE;
int y = (index / CHUNK_SIZE) % CHUNK_SIZE;
int z = index / (CHUNK_SIZE * CHUNK_SIZE);
return new Vector3Int(x, y, z);
}
/// <summary>
/// Convert local 3D coordinates to index
/// </summary>
public static int LocalToIndex(Vector3Int localPos)
{
return localPos.x + localPos.y * CHUNK_SIZE + localPos.z * CHUNK_SIZE * CHUNK_SIZE;
}
/// <summary>
/// Convert local coordinates (int) to index
/// </summary>
public static int LocalToIndex(int x, int y, int z)
{
return x + y * CHUNK_SIZE + z * CHUNK_SIZE * CHUNK_SIZE;
}
/// <summary>
/// Check if local coordinates are within valid range
/// </summary>
public static bool IsValidLocal(int x, int y, int z)
{
return x >= 0 && x < CHUNK_SIZE &&
y >= 0 && y < CHUNK_SIZE &&
z >= 0 && z < CHUNK_SIZE;
}
/// <summary>
/// Check if local position is within valid range
/// </summary>
public static bool IsValidLocal(Vector3Int local)
{
return IsValidLocal(local.x, local.y, local.z);
}
/// <summary>
/// Convert world hit point to local block index within chunk
/// </summary>
public int WorldPointToLocalIndex(Vector3 worldPoint)
{
// Get chunk origin in world space
Vector3 chunkWorldOrigin = WorldOrigin;
// Calculate offset from chunk origin (in grid units, assuming 1 unit per block)
float cellSize = BuildManager.Instance != null ? BuildManager.Instance.cellSize : 1f;
Vector3 offset = (worldPoint - chunkWorldOrigin) / cellSize;
// Convert to local coordinates (add small epsilon to handle edge cases)
int lx = Mathf.Clamp(Mathf.FloorToInt(offset.x + 0.5f), 0, CHUNK_SIZE - 1);
int ly = Mathf.Clamp(Mathf.FloorToInt(offset.y + 0.5f), 0, CHUNK_SIZE - 1);
int lz = Mathf.Clamp(Mathf.FloorToInt(offset.z + 0.5f), 0, CHUNK_SIZE - 1);
return LocalToIndex(lx, ly, lz);
}
public override bool Equals(object obj)
{
if (obj is ChunkCoord other)
{
return chunkPos == other.chunkPos;
}
return false;
}
public override int GetHashCode()
{
return chunkPos.GetHashCode();
}
public static bool operator ==(ChunkCoord a, ChunkCoord b)
{
return a.chunkPos == b.chunkPos;
}
public static bool operator !=(ChunkCoord a, ChunkCoord b)
{
return a.chunkPos != b.chunkPos;
}
public override string ToString()
{
return $"ChunkCoord({chunkPos.x}, {chunkPos.y}, {chunkPos.z})";
}
}