드래그로 대량 건설 기능 추가
Kaykit Medival 누락사항 추가 기본 성벽 및 성문 변경
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
@@ -21,6 +22,12 @@ namespace Northbound
|
||||
[Header("Debug Visualization")]
|
||||
public bool showGridBounds = true;
|
||||
|
||||
[Header("Drag Building")]
|
||||
[Tooltip("드래그 건설 활성화")]
|
||||
public bool enableDragBuilding = true;
|
||||
[Tooltip("드래그 건설 시 최대 건물 수")]
|
||||
public int maxDragBuildingCount = 50;
|
||||
|
||||
private bool isBuildModeActive = false;
|
||||
private GameObject previewObject;
|
||||
private int currentRotation = 0; // 0-3
|
||||
@@ -28,6 +35,12 @@ namespace Northbound
|
||||
private Renderer[] previewRenderers;
|
||||
private PlayerInputActions _inputActions;
|
||||
|
||||
// 드래그 건설 관련
|
||||
private bool isDragging = false;
|
||||
private Vector3 dragStartPosition;
|
||||
private List<GameObject> dragPreviewObjects = new List<GameObject>();
|
||||
private List<Vector3> dragBuildingPositions = new List<Vector3>();
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (!IsOwner) return;
|
||||
@@ -35,7 +48,9 @@ namespace Northbound
|
||||
_inputActions = new PlayerInputActions();
|
||||
_inputActions.Player.ToggleBuildMode.performed += OnToggleBuildMode;
|
||||
_inputActions.Player.Rotate.performed += OnRotate;
|
||||
_inputActions.Player.Build.performed += OnBuild;
|
||||
_inputActions.Player.Build.performed += OnBuildPressed;
|
||||
_inputActions.Player.Build.canceled += OnBuildReleased;
|
||||
_inputActions.Player.Cancel.performed += OnCancel;
|
||||
_inputActions.Enable();
|
||||
|
||||
// Create default materials if not assigned
|
||||
@@ -103,10 +118,14 @@ namespace Northbound
|
||||
{
|
||||
_inputActions.Player.ToggleBuildMode.performed -= OnToggleBuildMode;
|
||||
_inputActions.Player.Rotate.performed -= OnRotate;
|
||||
_inputActions.Player.Build.performed -= OnBuild;
|
||||
_inputActions.Player.Build.performed -= OnBuildPressed;
|
||||
_inputActions.Player.Build.canceled -= OnBuildReleased;
|
||||
_inputActions.Player.Cancel.performed -= OnCancel;
|
||||
_inputActions.Disable();
|
||||
_inputActions.Dispose();
|
||||
}
|
||||
|
||||
ClearDragPreviews();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
@@ -115,7 +134,24 @@ namespace Northbound
|
||||
|
||||
if (isBuildModeActive)
|
||||
{
|
||||
UpdatePreviewPosition();
|
||||
if (isDragging && enableDragBuilding)
|
||||
{
|
||||
UpdateDragPreview();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdatePreviewPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCancel(InputAction.CallbackContext context)
|
||||
{
|
||||
// 드래그 중일 때만 취소
|
||||
if (isDragging && isBuildModeActive)
|
||||
{
|
||||
CancelDrag();
|
||||
Debug.Log("<color=yellow>[BuildingPlacement] 드래그 건설 취소됨</color>");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +177,15 @@ namespace Northbound
|
||||
BuildingQuickslotUI.Instance.HideQuickslot();
|
||||
}
|
||||
|
||||
// 드래그 중이었다면 취소
|
||||
if (isDragging)
|
||||
{
|
||||
CancelDrag();
|
||||
Debug.Log("<color=yellow>[BuildingPlacement] 건설 모드 종료로 드래그 취소됨</color>");
|
||||
}
|
||||
|
||||
DestroyPreview();
|
||||
ClearDragPreviews();
|
||||
}
|
||||
|
||||
Debug.Log($"[BuildingPlacement] 건설 모드 {(isBuildModeActive ? "활성화" : "비활성화")}");
|
||||
@@ -162,6 +206,13 @@ namespace Northbound
|
||||
selectedBuildingIndex = index;
|
||||
currentRotation = 0; // 회전 초기화
|
||||
|
||||
// 드래그 중이었다면 취소
|
||||
if (isDragging)
|
||||
{
|
||||
CancelDrag();
|
||||
Debug.Log("<color=yellow>[BuildingPlacement] 건물 변경으로 드래그 취소됨</color>");
|
||||
}
|
||||
|
||||
// 프리뷰 다시 생성
|
||||
if (isBuildModeActive)
|
||||
{
|
||||
@@ -276,10 +327,234 @@ namespace Northbound
|
||||
{
|
||||
if (!isBuildModeActive) return;
|
||||
|
||||
// 드래그 중에는 회전 불가
|
||||
if (isDragging)
|
||||
{
|
||||
Debug.Log("<color=yellow>[BuildingPlacement] 드래그 중에는 회전할 수 없습니다</color>");
|
||||
return;
|
||||
}
|
||||
|
||||
currentRotation = (currentRotation + 1) % 4;
|
||||
}
|
||||
|
||||
private void OnBuild(InputAction.CallbackContext context)
|
||||
private void OnBuildPressed(InputAction.CallbackContext context)
|
||||
{
|
||||
if (!isBuildModeActive || IsPointerOverUI())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (enableDragBuilding)
|
||||
{
|
||||
// 드래그 시작
|
||||
Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
|
||||
if (Physics.Raycast(ray, out RaycastHit hit, maxPlacementDistance, groundLayer))
|
||||
{
|
||||
isDragging = true;
|
||||
dragStartPosition = hit.point;
|
||||
|
||||
// 메인 프리뷰 숨기기
|
||||
if (previewObject != null)
|
||||
{
|
||||
previewObject.SetActive(false);
|
||||
}
|
||||
|
||||
Debug.Log("<color=cyan>[BuildingPlacement] 드래그 건설 시작 (ESC로 취소 가능)</color>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBuildReleased(InputAction.CallbackContext context)
|
||||
{
|
||||
if (!isBuildModeActive) return;
|
||||
|
||||
if (enableDragBuilding && isDragging)
|
||||
{
|
||||
// 드래그 종료 - 배치 실행
|
||||
ExecuteDragBuild();
|
||||
isDragging = false;
|
||||
|
||||
// 메인 프리뷰 다시 표시
|
||||
if (previewObject != null)
|
||||
{
|
||||
previewObject.SetActive(true);
|
||||
}
|
||||
|
||||
ClearDragPreviews();
|
||||
}
|
||||
else if (!enableDragBuilding)
|
||||
{
|
||||
// 단일 건물 배치 (드래그 비활성화 시)
|
||||
OnBuild();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 취소
|
||||
/// </summary>
|
||||
private void CancelDrag()
|
||||
{
|
||||
if (!isDragging) return;
|
||||
|
||||
isDragging = false;
|
||||
|
||||
// 메인 프리뷰 다시 표시
|
||||
if (previewObject != null)
|
||||
{
|
||||
previewObject.SetActive(true);
|
||||
}
|
||||
|
||||
// 드래그 프리뷰 정리
|
||||
ClearDragPreviews();
|
||||
}
|
||||
|
||||
private void UpdateDragPreview()
|
||||
{
|
||||
if (BuildingManager.Instance == null) return;
|
||||
|
||||
Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
|
||||
if (!Physics.Raycast(ray, out RaycastHit hit, maxPlacementDistance, groundLayer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Debug.LogWarning($"[BuildingPlacement] 드래그 건설 최대 개수 도달: {maxDragBuildingCount}");
|
||||
break;
|
||||
}
|
||||
|
||||
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>());
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Vector3> CalculateDragBuildingPositions(Vector3 start, Vector3 end, BuildingData data)
|
||||
{
|
||||
List<Vector3> positions = new List<Vector3>();
|
||||
|
||||
// 그리드에 스냅
|
||||
Vector3 snappedStart = BuildingManager.Instance.SnapToGrid(start);
|
||||
Vector3 snappedEnd = BuildingManager.Instance.SnapToGrid(end);
|
||||
|
||||
// 건물 크기 고려
|
||||
Vector3 size = data.GetSize(currentRotation);
|
||||
float gridSize = BuildingManager.Instance.gridSize;
|
||||
float stepX = Mathf.Max(size.x, gridSize);
|
||||
float stepZ = Mathf.Max(size.z, gridSize);
|
||||
|
||||
// 드래그 방향 계산
|
||||
Vector3 direction = snappedEnd - snappedStart;
|
||||
float distanceX = Mathf.Abs(direction.x);
|
||||
float distanceZ = Mathf.Abs(direction.z);
|
||||
|
||||
int countX = Mathf.Max(1, Mathf.RoundToInt(distanceX / stepX) + 1);
|
||||
int countZ = Mathf.Max(1, Mathf.RoundToInt(distanceZ / stepZ) + 1);
|
||||
|
||||
float dirX = direction.x >= 0 ? 1 : -1;
|
||||
float dirZ = direction.z >= 0 ? 1 : -1;
|
||||
|
||||
// 그리드 패턴으로 위치 생성
|
||||
for (int x = 0; x < countX; x++)
|
||||
{
|
||||
for (int z = 0; z < countZ; z++)
|
||||
{
|
||||
Vector3 pos = snappedStart + new Vector3(
|
||||
x * stepX * dirX,
|
||||
0,
|
||||
z * stepZ * dirZ
|
||||
);
|
||||
positions.Add(pos);
|
||||
}
|
||||
}
|
||||
|
||||
return positions;
|
||||
}
|
||||
|
||||
private void ExecuteDragBuild()
|
||||
{
|
||||
if (dragBuildingPositions.Count == 0)
|
||||
{
|
||||
Debug.Log("<color=yellow>[BuildingPlacement] 배치 가능한 건물이 없습니다.</color>");
|
||||
return;
|
||||
}
|
||||
|
||||
BuildingData selectedData = BuildingManager.Instance.availableBuildings[selectedBuildingIndex];
|
||||
|
||||
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()
|
||||
{
|
||||
foreach (var preview in dragPreviewObjects)
|
||||
{
|
||||
if (preview != null)
|
||||
{
|
||||
Destroy(preview);
|
||||
}
|
||||
}
|
||||
dragPreviewObjects.Clear();
|
||||
dragBuildingPositions.Clear();
|
||||
}
|
||||
|
||||
private void OnBuild()
|
||||
{
|
||||
if (!isBuildModeActive || previewObject == null) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user