건설 모드에서 클릭이 잘 작동하지 않는 문제 수정

건설 모드 UI가 클릭되어 건설되지 않는 문제 수정
JMO Asset 위치 조정
Tower, Monster, Creep의 Hit/Destroy FX Prefab 설정 (Template Level)
Tower에 체력바 추가 (최초 건설 시, 체력 변경 시 등장)
Tower 관련 디버깅 로그 정리
건설 토대의 사이즈가 비정상적인 문제 수정
This commit is contained in:
2026-02-25 01:41:58 +09:00
parent 3dabf9f9a4
commit f3923079a4
1047 changed files with 897 additions and 373 deletions

View File

@@ -42,6 +42,9 @@ namespace Northbound
private List<GameObject> dragPreviewObjects = new List<GameObject>();
private List<Vector3> dragBuildingPositions = new List<Vector3>();
// UI 체크 캐싱 (Input System 콜백 내에서 IsPointerOverGameObject() 사용 불가)
private bool _isPointerOverUI = false;
public override void OnNetworkSpawn()
{
if (!IsOwner) return;
@@ -133,6 +136,9 @@ namespace Northbound
{
if (!IsOwner) return;
// UI 체크 캐싱 (Input System 콜백 내에서 사용하기 위해)
_isPointerOverUI = CheckPointerOverUI();
if (isBuildModeActive)
{
if (isDragging && enableDragBuilding)
@@ -152,7 +158,6 @@ namespace Northbound
if (isDragging && isBuildModeActive)
{
CancelDrag();
Debug.Log("<color=yellow>[BuildingPlacement] 드래그 건설 취소됨</color>");
}
// 건설 모드 활성화 상태면 건설 모드 종료
else if (isBuildModeActive)
@@ -164,7 +169,6 @@ namespace Northbound
}
DestroyPreview();
ClearDragPreviews();
Debug.Log("<color=yellow>[BuildingPlacement] 건설 모드 취소됨</color>");
}
}
@@ -194,7 +198,6 @@ namespace Northbound
if (isDragging)
{
CancelDrag();
Debug.Log("<color=yellow>[BuildingPlacement] 건설 모드 종료로 드래그 취소됨</color>");
}
DestroyPreview();
@@ -221,7 +224,6 @@ namespace Northbound
if (isDragging)
{
CancelDrag();
Debug.Log("<color=yellow>[BuildingPlacement] 건물 변경으로 드래그 취소됨</color>");
}
// 프리뷰 다시 생성
@@ -372,18 +374,14 @@ namespace Northbound
if (!isBuildModeActive) return;
// 드래그 중에는 회전 불가
if (isDragging)
{
Debug.Log("<color=yellow>[BuildingPlacement] 드래그 중에는 회전할 수 없습니다</color>");
return;
}
if (isDragging) return;
currentRotation = (currentRotation + 1) % 4;
}
private void OnBuildPressed(InputAction.CallbackContext context)
{
if (!isBuildModeActive || IsPointerOverUI())
if (!isBuildModeActive || _isPointerOverUI)
{
return;
}
@@ -396,14 +394,12 @@ namespace Northbound
{
isDragging = true;
dragStartPosition = hit.point;
// 메인 프리뷰 숨기기
if (previewObject != null)
{
previewObject.SetActive(false);
}
Debug.Log("<color=cyan>[BuildingPlacement] 드래그 건설 시작 (ESC로 취소 가능)</color>");
}
}
}
@@ -500,6 +496,9 @@ namespace Northbound
GameObject preview = Instantiate(data.prefab);
// 프리뷰가 보이도록 명시적으로 활성화
preview.SetActive(true);
// Remove NetworkObject and Building components
if (preview.GetComponent<NetworkObject>() != null)
Destroy(preview.GetComponent<NetworkObject>());
@@ -588,30 +587,41 @@ namespace Northbound
private void ExecuteDragBuild()
{
if (dragBuildingPositions.Count == 0)
{
Debug.Log("<color=yellow>[BuildingPlacement] 배치 가능한 건물이 없습니다.</color>");
return;
}
TowerData selectedData = BuildingManager.Instance.GetBuildableBuildings()[selectedBuildingIndex];
// Check affordability
var coreResourceManager = CoreResourceManager.Instance;
if (coreResourceManager == null || !coreResourceManager.CanAfford(selectedData.mana * dragBuildingPositions.Count))
// 드래그 위치가 없으면 현재 프리뷰 위치로 단일 건설 시도
if (dragBuildingPositions.Count == 0)
{
if (previewObject != null && previewObject.activeSelf)
{
// 현재 프리뷰 위치에서 건설 시도
Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
if (Physics.Raycast(ray, out RaycastHit hit, maxPlacementDistance, groundLayer))
{
if (BuildingManager.Instance.IsValidPlacement(selectedData, hit.point, currentRotation, out Vector3 groundPosition))
{
var coreResourceManager = CoreResourceManager.Instance;
if (coreResourceManager == null || coreResourceManager.CanAfford(selectedData.mana))
{
BuildingManager.Instance.RequestPlaceFoundation(selectedBuildingIndex, groundPosition, currentRotation);
}
}
}
}
return;
}
// Check affordability
var coreResourceManager2 = CoreResourceManager.Instance;
if (coreResourceManager2 == null || !coreResourceManager2.CanAfford(selectedData.mana * dragBuildingPositions.Count))
{
Debug.Log("<color=yellow>[BuildingPlacement] 자원이 부족합니다.</color>");
return;
}
int successCount = 0;
foreach (var position in dragBuildingPositions)
{
BuildingManager.Instance.RequestPlaceFoundation(selectedBuildingIndex, position, currentRotation);
successCount++;
}
Debug.Log($"<color=cyan>[BuildingPlacement] 드래그 건설 완료: {successCount}개의 {selectedData.buildingName} 배치 시도</color>");
}
private void ClearDragPreviews()
@@ -632,11 +642,7 @@ namespace Northbound
if (!isBuildModeActive || previewObject == null) return;
// UI 위에서 클릭한 경우 무시
if (IsPointerOverUI())
{
Debug.Log("<color=cyan>[BuildingPlacement] UI 위에서 클릭함 - 건설 취소</color>");
return;
}
if (_isPointerOverUI) return;
// Get placement position
Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
@@ -648,7 +654,6 @@ namespace Northbound
var coreResourceManager = CoreResourceManager.Instance;
if (coreResourceManager != null && !coreResourceManager.CanAfford(selectedData.mana))
{
Debug.Log("<color=yellow>[BuildingPlacement] 자원이 부족합니다.</color>");
return;
}
@@ -656,33 +661,37 @@ namespace Northbound
{
// 토대 배치 요청
BuildingManager.Instance.RequestPlaceFoundation(selectedBuildingIndex, groundPosition, currentRotation);
Debug.Log($"<color=cyan>[BuildingPlacement] 건설 시작: {selectedData.buildingName}</color>");
}
else
{
Debug.Log("<color=yellow>[BuildingPlacement] 배치할 수 없는 위치입니다.</color>");
}
}
}
/// <summary>
/// 마우스 포인터가 UI 위에 있는지 확인
/// 마우스 포인터가 건설 UI 위에 있는지 확인 (Update에서만 호출)
/// </summary>
private bool IsPointerOverUI()
private bool CheckPointerOverUI()
{
// EventSystem이 없으면 UI 체크 불가능
if (EventSystem.current == null)
return false;
// New Input System을 사용하는 경우
if (Mouse.current != null)
if (Mouse.current == null)
return false;
Vector2 mousePosition = Mouse.current.position.ReadValue();
// BuildingQuickslotUI의 패널이 마우스 아래에 있는지 확인
if (BuildingQuickslotUI.Instance != null)
{
Vector2 mousePosition = Mouse.current.position.ReadValue();
return EventSystem.current.IsPointerOverGameObject();
var quickslotUI = BuildingQuickslotUI.Instance;
// quickslotPanel이 활성화되어 있고, 마우스가 그 위에 있으면 true
if (quickslotUI.IsMouseOverQuickslot(mousePosition))
{
return true;
}
}
// Legacy Input System (폴백)
return EventSystem.current.IsPointerOverGameObject();
return false;
}
/// <summary>