Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save khokhryakov47/a1cb8190683b045f549f6c1ca0fff237 to your computer and use it in GitHub Desktop.
Save khokhryakov47/a1cb8190683b045f549f6c1ca0fff237 to your computer and use it in GitHub Desktop.
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
[RequireComponent(typeof(BuildingGrid))]
public class Builder : MonoBehaviour
{
[SerializeField] private EventStorage _eventStorage;
[SerializeField] private Timer _buildingTimerTemplate;
private BuildingGrid _buildingGrid;
private BuildingDrawing _currentBuildingDrawing;
private Building _currentBuilding;
private Camera _camera;
private Vector2Int _desiredPlace;
private bool _placingConfirm;
private ConfirmMenu _confirmMenu;
private bool _buildingAvailable;
public event UnityAction<BuildingDrawing> BuildingPlaced;
public event UnityAction BuildingCompleted;
private void Awake()
{
_camera = Camera.main;
_buildingGrid = GetComponent<BuildingGrid>();
}
public void StartPlacingBuilding(BuildingDrawing buildingDrawing)
{
if (_currentBuilding != null)
{
Destroy(_currentBuilding.gameObject);
}
_currentBuildingDrawing = buildingDrawing;
_currentBuilding = Instantiate(_currentBuildingDrawing.Template);
_currentBuilding.name = _currentBuilding.name.Replace("(Clone)", string.Empty);
_confirmMenu = _currentBuilding.GetComponentInChildren<ConfirmMenu>();
_confirmMenu.BuildingConfirmed += OnConfirmBuilding;
_confirmMenu.BuildingRejected += OnBuildingRejected;
StartCoroutine(Placing());
}
private IEnumerator Placing()
{
while (_currentBuilding != null)
{
var groundPlane = new Plane(Vector3.up, Vector3.zero);
Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
if (groundPlane.Raycast(ray, out float position))
{
Vector3 worldPosition = ray.GetPoint(position);
int desiredPlaceX = Mathf.RoundToInt(worldPosition.x);
int desiredPlaceY = Mathf.RoundToInt(worldPosition.z);
_desiredPlace = new Vector2Int(desiredPlaceX, desiredPlaceY);
_buildingAvailable = CheckPlaceAvailability(_desiredPlace, _currentBuilding);
_currentBuilding.transform.position = new Vector3(_desiredPlace.x, 0, _desiredPlace.y);
_currentBuilding.SetTransparent(_buildingAvailable);
if (Input.GetKeyDown(KeyCode.Space))
PlaceBuilding();
}
yield return null;
}
}
private bool CheckPlaceAvailability(Vector2Int desiredPlace, Building currentBuilding)
{
bool available = true;
if (desiredPlace.x < 0 || desiredPlace.x > _buildingGrid.GridSize.x - currentBuilding.Size.x)
available = false;
if (desiredPlace.y < 0 || desiredPlace.y > _buildingGrid.GridSize.x - currentBuilding.Size.y)
available = false;
if (available && _buildingGrid.IsPlaceTaken(desiredPlace.x, desiredPlace.y, _currentBuilding))
available = false;
return available;
}
private void PlaceBuilding()
{
if (_buildingAvailable)
{
_buildingGrid.PlaceBuilding(_desiredPlace.x, _desiredPlace.y, _currentBuilding);
_currentBuilding.Activate(_currentBuildingDrawing, _eventStorage, _buildingTimerTemplate);
BuildingPlaced?.Invoke(_currentBuildingDrawing);
_currentBuilding.BuildingCompleted += OnBuildingCompleted;
ResetCurrentBuilding();
}
}
private void OnBuildingCompleted(Building building)
{
building.BuildingCompleted -= OnBuildingCompleted;
BuildingCompleted?.Invoke();
}
private void CancelBuild()
{
ResetCurrentBuilding();
}
private void ResetCurrentBuilding()
{
_confirmMenu.BuildingConfirmed -= OnConfirmBuilding;
_confirmMenu.BuildingRejected -= OnBuildingRejected;
Destroy(_confirmMenu.gameObject);
_currentBuilding = null;
_currentBuildingDrawing = null;
_buildingAvailable = false;
}
private void OnConfirmBuilding()
{
PlaceBuilding();
}
private void OnBuildingRejected()
{
CancelBuild();
}
}
@rokiboxofficial
Copy link

if (_currentBuilding != null)
{
Destroy(_currentBuilding.gameObject);
}
if (available && _buildingGrid.IsPlaceTaken(desiredPlace.x, desiredPlace.y, _currentBuilding))
available = false;
Вот он, профессиональный coding-style

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment