네트워크 멀티플레이 대응

This commit is contained in:
2026-01-31 20:49:23 +09:00
parent 1152093521
commit c5bcf265d0
69 changed files with 2766 additions and 1392 deletions

View File

@@ -225,61 +225,71 @@ namespace Northbound
private void CreatePreview()
{
if (!ValidateBuildingData(selectedBuildingIndex, out BuildingData data))
{
return;
}
previewObject = Instantiate(data.prefab);
SetupPreviewObject(previewObject, validMaterial);
Debug.Log($"[BuildingPlacement] 프리뷰 생성됨: {data.buildingName}");
}
private bool ValidateBuildingData(int index, out BuildingData data)
{
data = null;
if (BuildingManager.Instance == null)
{
Debug.LogWarning("[BuildingPlacement] BuildingManager가 없습니다.");
return;
return false;
}
if (selectedBuildingIndex < 0 || selectedBuildingIndex >= BuildingManager.Instance.availableBuildings.Count)
if (index < 0 || index >= BuildingManager.Instance.availableBuildings.Count)
{
Debug.LogWarning($"[BuildingPlacement] 유효하지 않은 건물 인덱스: {selectedBuildingIndex}");
return;
Debug.LogWarning($"[BuildingPlacement] 유효하지 않은 건물 인덱스: {index}");
return false;
}
BuildingData data = BuildingManager.Instance.availableBuildings[selectedBuildingIndex];
data = BuildingManager.Instance.availableBuildings[index];
if (data == null || data.prefab == null)
{
Debug.LogWarning("[BuildingPlacement] BuildingData 또는 Prefab이 없습니다.");
return;
return false;
}
// 완성 건물 프리팹으로 프리뷰 생성 (사용자가 완성 모습을 볼 수 있도록)
previewObject = Instantiate(data.prefab);
// Remove NetworkObject component from preview
NetworkObject netObj = previewObject.GetComponent<NetworkObject>();
return true;
}
private void SetupPreviewObject(GameObject previewObj, Material material)
{
NetworkObject netObj = previewObj.GetComponent<NetworkObject>();
if (netObj != null)
{
Destroy(netObj);
}
// Remove Building component from preview
Building building = previewObject.GetComponent<Building>();
Building building = previewObj.GetComponent<Building>();
if (building != null)
{
Destroy(building);
}
// Apply ghost materials
previewRenderers = previewObject.GetComponentsInChildren<Renderer>();
foreach (var renderer in previewRenderers)
Renderer[] renderers = previewObj.GetComponentsInChildren<Renderer>();
foreach (var renderer in renderers)
{
Material[] mats = new Material[renderer.materials.Length];
for (int i = 0; i < mats.Length; i++)
{
mats[i] = validMaterial;
mats[i] = material;
}
renderer.materials = mats;
}
// Disable colliders in preview
foreach (var collider in previewObject.GetComponentsInChildren<Collider>())
foreach (var collider in previewObj.GetComponentsInChildren<Collider>())
{
collider.enabled = false;
}
Debug.Log($"[BuildingPlacement] 프리뷰 생성됨: {data.buildingName}");
}
private void DestroyPreview()
@@ -297,29 +307,33 @@ namespace Northbound
return;
Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
if (Physics.Raycast(ray, out RaycastHit hit, maxPlacementDistance, groundLayer))
{
BuildingData data = BuildingManager.Instance.availableBuildings[selectedBuildingIndex];
// Check if placement is valid
bool isValid = BuildingManager.Instance.IsValidPlacement(data, hit.point, currentRotation, out Vector3 snappedPosition);
// Update preview position (placementOffset 적용)
previewObject.transform.position = snappedPosition + data.placementOffset;
previewObject.transform.rotation = Quaternion.Euler(0, currentRotation * 90f, 0);
// Update material based on validity
Material targetMat = isValid ? validMaterial : invalidMaterial;
foreach (var renderer in previewRenderers)
UpdatePreviewMaterials(previewRenderers, targetMat);
}
}
private void UpdatePreviewMaterials(Renderer[] renderers, Material material)
{
if (renderers == null) return;
foreach (var renderer in renderers)
{
Material[] mats = new Material[renderer.materials.Length];
for (int i = 0; i < mats.Length; i++)
{
Material[] mats = new Material[renderer.materials.Length];
for (int i = 0; i < mats.Length; i++)
{
mats[i] = targetMat;
}
renderer.materials = mats;
mats[i] = material;
}
renderer.materials = mats;
}
}
@@ -419,16 +433,13 @@ namespace Northbound
}
BuildingData data = BuildingManager.Instance.availableBuildings[selectedBuildingIndex];
// 드래그 영역 계산
Vector3 dragEndPosition = hit.point;
List<Vector3> positions = CalculateDragBuildingPositions(dragStartPosition, dragEndPosition, data);
// 기존 프리뷰 정리
ClearDragPreviews();
// 새로운 프리뷰 생성
dragBuildingPositions.Clear();
foreach (var pos in positions)
{
if (dragPreviewObjects.Count >= maxDragBuildingCount)
@@ -440,38 +451,14 @@ namespace Northbound
bool isValid = BuildingManager.Instance.IsValidPlacement(data, pos, currentRotation, out Vector3 snappedPosition);
GameObject preview = Instantiate(data.prefab);
// Remove NetworkObject and Building components
if (preview.GetComponent<NetworkObject>() != null)
Destroy(preview.GetComponent<NetworkObject>());
if (preview.GetComponent<Building>() != null)
Destroy(preview.GetComponent<Building>());
Material targetMat = isValid ? validMaterial : invalidMaterial;
SetupPreviewObject(preview, targetMat);
// Set position and rotation
preview.transform.position = snappedPosition + data.placementOffset;
preview.transform.rotation = Quaternion.Euler(0, currentRotation * 90f, 0);
// Apply materials
Material targetMat = isValid ? validMaterial : invalidMaterial;
Renderer[] renderers = preview.GetComponentsInChildren<Renderer>();
foreach (var renderer in renderers)
{
Material[] mats = new Material[renderer.materials.Length];
for (int i = 0; i < mats.Length; i++)
{
mats[i] = targetMat;
}
renderer.materials = mats;
}
// Disable colliders
foreach (var collider in preview.GetComponentsInChildren<Collider>())
{
collider.enabled = false;
}
dragPreviewObjects.Add(preview);
if (isValid)
{
dragBuildingPositions.Add(snappedPosition);