Добавлены сисетмы сохранения, накопления ресурсов. Поставлена ратуша. Увеличивается уровен, открываются новые постройки. Перед постройкой объекта появляются границы. На каждом строении стоит цена постройки
This commit is contained in:
@@ -2,7 +2,7 @@ using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
// Управляет режимом строительства: показывает "призрак" здания под курсором,
|
||||
// проверяет ресурсы, спавнит здание в подтверждённой позиции.
|
||||
// проверяет ресурсы И пересечение с другими зданиями, спавнит здание в подтверждённой позиции.
|
||||
|
||||
public class BuildManager : MonoBehaviour
|
||||
{
|
||||
@@ -11,12 +11,21 @@ public class BuildManager : MonoBehaviour
|
||||
[Header("Все типы зданий в игре")]
|
||||
public List<BuildingData> allBuildings;
|
||||
|
||||
[Header("Проверка пересечения")]
|
||||
[Tooltip("Слой, на котором находятся коллайдеры уже построенных зданий")]
|
||||
public LayerMask buildingsLayerMask;
|
||||
[Tooltip("Небольшой отступ вокруг здания, чтобы дома не лепились впритык друг к другу")]
|
||||
public float placementPadding = 0.1f;
|
||||
|
||||
[Header("Визуал 'призрака' здания при размещении")]
|
||||
public Color validPlacementColor = new Color(1, 1, 1, 0.6f);
|
||||
public Color invalidPlacementColor = new Color(1, 0.3f, 0.3f, 0.6f);
|
||||
[Tooltip("Белая зона -- можно строить")]
|
||||
public Color validPlacementColor = new Color(1f, 1f, 1f, 0.6f);
|
||||
[Tooltip("Красная зона -- нельзя (либо не хватает ресурсов, либо место занято)")]
|
||||
public Color invalidPlacementColor = new Color(1f, 0.2f, 0.2f, 0.6f);
|
||||
|
||||
private BuildingData currentlyPlacing;
|
||||
private GameObject ghostObject;
|
||||
private Vector2 ghostSize;
|
||||
private Camera mainCam;
|
||||
|
||||
void Awake()
|
||||
@@ -31,29 +40,42 @@ public class BuildManager : MonoBehaviour
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (currentlyPlacing == null || ghostObject == null)
|
||||
return;
|
||||
|
||||
Vector3 worldPos = GetPointerWorldPosition();
|
||||
worldPos.z = 0;
|
||||
ghostObject.transform.position = worldPos;
|
||||
|
||||
bool canAfford = currentlyPlacing.CanAfford();
|
||||
SpriteRenderer sr = ghostObject.GetComponent<SpriteRenderer>();
|
||||
if (sr != null)
|
||||
sr.color = canAfford ? validPlacementColor : invalidPlacementColor;
|
||||
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
TryConfirmPlacement(worldPos);
|
||||
if (currentlyPlacing == null) return; // не в режиме строительства -- ничего не делаем
|
||||
|
||||
// Двигаем "призрак" здания за пальцем/мышкой
|
||||
Vector3 worldPos = GetPointerWorldPosition();
|
||||
worldPos.z = 0;
|
||||
ghostObject.transform.position = worldPos;
|
||||
|
||||
bool canAfford = currentlyPlacing.CanAfford();
|
||||
bool overlapping = IsOverlapping(worldPos);
|
||||
bool canPlace = canAfford && !overlapping;
|
||||
|
||||
SpriteRenderer sr = ghostObject.GetComponent<SpriteRenderer>();
|
||||
if (sr != null)
|
||||
sr.color = canPlace ? validPlacementColor : invalidPlacementColor;
|
||||
|
||||
// Подтверждение размещения по клику/тапу
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
TryConfirmPlacement(worldPos, canAfford, overlapping);
|
||||
}
|
||||
|
||||
// Отмена по правой кнопке / Escape
|
||||
if (Input.GetMouseButtonDown(1) || Input.GetKeyDown(KeyCode.Escape))
|
||||
{
|
||||
CancelPlacement();
|
||||
}
|
||||
}
|
||||
|
||||
if (Input.GetMouseButtonDown(1) || Input.GetKeyDown(KeyCode.Escape))
|
||||
// Проверка: пересекается ли здание в этой позиции с уже существующими постройками
|
||||
bool IsOverlapping(Vector3 position)
|
||||
{
|
||||
CancelPlacement();
|
||||
Vector2 checkSize = ghostSize + new Vector2(placementPadding, placementPadding);
|
||||
Collider2D hit = Physics2D.OverlapBox(position, checkSize, 0f, buildingsLayerMask);
|
||||
return hit != null;
|
||||
}
|
||||
}
|
||||
|
||||
// Список зданий, доступных для стройки ПРЯМО СЕЙЧАС (по уровню Ратуши)
|
||||
public List<BuildingData> GetAvailableBuildings()
|
||||
@@ -80,6 +102,11 @@ public class BuildManager : MonoBehaviour
|
||||
currentlyPlacing = data;
|
||||
|
||||
ghostObject = Instantiate(data.prefab);
|
||||
|
||||
// Замеряем размер здания по спрайту (работает даже если коллайдер потом выключим)
|
||||
SpriteRenderer ghostSr = ghostObject.GetComponent<SpriteRenderer>();
|
||||
ghostSize = ghostSr != null ? ghostSr.bounds.size : Vector2.one;
|
||||
|
||||
// Отключаем на "призраке" всё, что мешает (коллайдер, скрипты сбора ресурсов и т.д.)
|
||||
Collider2D col = ghostObject.GetComponent<Collider2D>();
|
||||
if (col != null) col.enabled = false;
|
||||
@@ -91,9 +118,15 @@ public class BuildManager : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
void TryConfirmPlacement(Vector3 position)
|
||||
void TryConfirmPlacement(Vector3 position, bool canAfford, bool overlapping)
|
||||
{
|
||||
if (!currentlyPlacing.CanAfford())
|
||||
if (overlapping)
|
||||
{
|
||||
Debug.Log("[СТРОЙКА] Здесь уже что-то построено!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!canAfford)
|
||||
{
|
||||
Debug.Log("[СТРОЙКА] Не хватает ресурсов!");
|
||||
return;
|
||||
@@ -102,6 +135,11 @@ public class BuildManager : MonoBehaviour
|
||||
currentlyPlacing.PayCost();
|
||||
|
||||
GameObject built = Instantiate(currentlyPlacing.prefab, position, Quaternion.identity);
|
||||
|
||||
// Ставим маркер, чтобы SaveManager потом знал, что это за здание при сохранении
|
||||
PlacedBuildingId idMarker = built.AddComponent<PlacedBuildingId>();
|
||||
idMarker.buildingName = currentlyPlacing.buildingName;
|
||||
|
||||
Debug.Log($"[СТРОЙКА] Построено: {currentlyPlacing.buildingName} в {position}");
|
||||
|
||||
Destroy(ghostObject);
|
||||
@@ -120,4 +158,4 @@ public class BuildManager : MonoBehaviour
|
||||
Vector3 screenPos = Input.mousePosition;
|
||||
return mainCam.ScreenToWorldPoint(screenPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user