지하 최적화
블록 프리팹 단위 -> 블록 청크 단위 스폰 기타 건설, 조준 관련 사이드이펙트 버그 수정
This commit is contained in:
126
Assets/Scripts/Underground/ChunkInteractionHandler.cs
Normal file
126
Assets/Scripts/Underground/ChunkInteractionHandler.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Handles interaction between players and chunk-based blocks.
|
||||
/// Converts raycast hits to block indices and manages damage/reveal requests.
|
||||
/// </summary>
|
||||
public static class ChunkInteractionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Result of a chunk interaction query
|
||||
/// </summary>
|
||||
public struct ChunkHitResult
|
||||
{
|
||||
public bool hasHit;
|
||||
public MineableChunk chunk;
|
||||
public int blockIndex;
|
||||
public Vector3 hitPoint;
|
||||
public Vector3 blockWorldPosition;
|
||||
public BlockData blockData;
|
||||
|
||||
public static ChunkHitResult None => new ChunkHitResult { hasHit = false };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to get chunk and block info from a raycast hit
|
||||
/// </summary>
|
||||
public static ChunkHitResult GetChunkHit(RaycastHit hit)
|
||||
{
|
||||
// Try to get MineableChunk from hit collider
|
||||
MineableChunk chunk = hit.collider.GetComponentInParent<MineableChunk>();
|
||||
if (chunk == null)
|
||||
{
|
||||
return ChunkHitResult.None;
|
||||
}
|
||||
|
||||
// Convert hit point to block index
|
||||
// Push slightly into the surface using the normal to get the correct block
|
||||
Vector3 insidePoint = hit.point - hit.normal * 0.01f;
|
||||
int blockIndex = chunk.WorldPointToBlockIndex(insidePoint);
|
||||
BlockData blockData = chunk.GetBlock(blockIndex);
|
||||
|
||||
// Skip if block is empty
|
||||
if (blockData.IsEmpty)
|
||||
{
|
||||
return ChunkHitResult.None;
|
||||
}
|
||||
|
||||
return new ChunkHitResult
|
||||
{
|
||||
hasHit = true,
|
||||
chunk = chunk,
|
||||
blockIndex = blockIndex,
|
||||
hitPoint = hit.point,
|
||||
blockWorldPosition = chunk.GetBlockWorldPosition(blockIndex),
|
||||
blockData = blockData
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to damage a block at a raycast hit point
|
||||
/// </summary>
|
||||
public static bool TryDamageAtPoint(RaycastHit hit, float damage)
|
||||
{
|
||||
ChunkHitResult result = GetChunkHit(hit);
|
||||
if (!result.hasHit) return false;
|
||||
|
||||
// Request damage on server
|
||||
result.chunk.DamageBlockServerRpc(result.blockIndex, (byte)Mathf.Min(255, damage));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to damage a block directly on a known chunk
|
||||
/// </summary>
|
||||
public static bool TryDamageBlock(MineableChunk chunk, int blockIndex, float damage)
|
||||
{
|
||||
if (chunk == null) return false;
|
||||
|
||||
BlockData block = chunk.GetBlock(blockIndex);
|
||||
if (block.IsEmpty) return false;
|
||||
|
||||
chunk.DamageBlockServerRpc(blockIndex, (byte)Mathf.Min(255, damage));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to reveal a block at a raycast hit point
|
||||
/// </summary>
|
||||
public static bool TryRevealAtPoint(RaycastHit hit)
|
||||
{
|
||||
MineableChunk chunk = hit.collider.GetComponentInParent<MineableChunk>();
|
||||
if (chunk == null) return false;
|
||||
|
||||
int blockIndex = chunk.WorldPointToBlockIndex(hit.point - hit.normal * 0.1f);
|
||||
BlockData blockData = chunk.GetBlock(blockIndex);
|
||||
|
||||
if (blockData.IsEmpty || blockData.IsDiscovered) return false;
|
||||
|
||||
chunk.RevealBlockServerRpc(blockIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a sphere cast to find a targetable block in a chunk
|
||||
/// </summary>
|
||||
public static ChunkHitResult SphereCastForBlock(Vector3 origin, Vector3 direction, float radius, float maxDistance, LayerMask chunkLayer)
|
||||
{
|
||||
if (Physics.SphereCast(origin, radius, direction, out RaycastHit hit, maxDistance, chunkLayer))
|
||||
{
|
||||
return GetChunkHit(hit);
|
||||
}
|
||||
return ChunkHitResult.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a raycast to find a targetable block in a chunk
|
||||
/// </summary>
|
||||
public static ChunkHitResult RaycastForBlock(Vector3 origin, Vector3 direction, float maxDistance, LayerMask chunkLayer)
|
||||
{
|
||||
if (Physics.Raycast(origin, direction, out RaycastHit hit, maxDistance, chunkLayer))
|
||||
{
|
||||
return GetChunkHit(hit);
|
||||
}
|
||||
return ChunkHitResult.None;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user