Untitled
using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using DG.Tweening; public class DraggyRoad : MonoBehaviour { [SerializeField] private GameObject straightTemplate; [SerializeField] private GameObject cornerTemplate; [SerializeField] private float gridScale = 1.5f; [SerializeField] private ToastManager toastManager; [Header("UI Controls")] [SerializeField] private Button upButton; [SerializeField] private Button downButton; [SerializeField] private Button leftButton; [SerializeField] private Button rightButton; [Header("Sound Effects")] [SerializeField] private AudioClip roadPlaceSound; [Header("Animation Settings")] [SerializeField] private float placementDuration = 0.3f; [SerializeField] private Ease placementEase = Ease.OutBack; private AudioSource audioSource; private bool soundEnabled = true; private Vector3Int lastPosition; private float lastAngle; private GameObject lastPlacedSection; private Dictionary<Vector3Int, GameObject> roadTiles = new(); private GameObject[] roadTilesLoop = new GameObject[30]; private int loopStoreIndex = 0; private int loopRetrieveIndex = 0; private int lastLoopStoreIndex = 0; void Start() { audioSource = gameObject.AddComponent<AudioSource>(); audioSource.playOnAwake = false; soundEnabled = false; InitializeRoad(); soundEnabled = true; upButton.onClick.AddListener(() =>{PlaceRoad(Vector3Int.up, 90f);}); downButton.onClick.AddListener(() =>{PlaceRoad(Vector3Int.down, -90f);}); leftButton.onClick.AddListener(() =>{PlaceRoad(Vector3Int.left, 180f);}); rightButton.onClick.AddListener(() =>{PlaceRoad(Vector3Int.right, 0f);}); } private void InitializeRoad() { Vector3Int startingPosition = new(-7, 0, 0); Vector3 worldStartPosition = (Vector3)startingPosition * gridScale; lastPlacedSection = Instantiate(straightTemplate, worldStartPosition, Quaternion.Euler(0, 0, 0)); roadTiles.Add(startingPosition, lastPlacedSection); roadTilesLoop[0] = lastPlacedSection; loopStoreIndex = 1; loopRetrieveIndex = 0; lastLoopStoreIndex = 0; lastPosition = startingPosition; lastAngle = 0; for (int i = 0; i < 6; i++) { TryPlaceRoad(Vector3Int.right, straightTemplate, 0f); } } private void PlaceRoad(Vector3Int direction, float angle) { TryPlaceRoad(direction, straightTemplate, angle); } void TryPlaceRoad(Vector3Int direction, GameObject template, float angle) { Vector3Int newPosition = lastPosition + direction; Vector3 worldPosition = (Vector3)newPosition * gridScale; if (CanPlaceRoad(newPosition) && IsWithinCameraBounds(worldPosition)) { GameObject newRoad = Instantiate(template, worldPosition, Quaternion.Euler(0, 0, angle)); newRoad.transform.localScale = Vector3.zero; newRoad.transform.DOScale(Vector3.one, placementDuration) .SetEase(placementEase); roadTiles[newPosition] = newRoad; if (roadTilesLoop[loopStoreIndex] != null) { Destroy(roadTilesLoop[loopStoreIndex]); } roadTilesLoop[loopStoreIndex] = newRoad; if (angle != lastAngle) { Vector3 cornerPosition = (Vector3)lastPosition * gridScale; Destroy(lastPlacedSection); GameObject cornerPiece = null; switch (angle - lastAngle) { case 90: case -270: cornerPiece = Instantiate(cornerTemplate, cornerPosition, Quaternion.Euler(0, 0, lastAngle)); break; case -90: case 270: cornerPiece = Instantiate(cornerTemplate, cornerPosition, Quaternion.Euler(0, 0, lastAngle + 90)); break; } if (cornerPiece != null) { lastPlacedSection = cornerPiece; roadTiles[lastPosition] = cornerPiece; roadTilesLoop[lastLoopStoreIndex] = cornerPiece; } } lastLoopStoreIndex = loopStoreIndex; loopStoreIndex = (loopStoreIndex + 1) % roadTilesLoop.Length; lastAngle = angle; lastPlacedSection = newRoad; lastPosition += direction; if (soundEnabled) { PlayRoadPlaceSound(); } } else { if (!IsWithinCameraBounds(worldPosition)) { toastManager.ShowToast("Road out of bounds!"); } else { toastManager.ShowToast("Cannot place road here!"); } } } private void PlayRoadPlaceSound() { if (audioSource != null && roadPlaceSound != null) { audioSource.PlayOneShot(roadPlaceSound); } } bool IsWithinCameraBounds(Vector3 position) { Camera mainCamera = Camera.main; if (mainCamera == null) return false; Vector3 viewportPoint = mainCamera.WorldToViewportPoint(position); return viewportPoint.x >= 0 && viewportPoint.x <= 1 && viewportPoint.y >= 0 && viewportPoint.y <= 1; } bool CanPlaceRoad(Vector3Int position) { if (roadTiles.TryGetValue(position, out GameObject result) && result != null) { return false; } Vector3 worldPosition = (Vector3)position * gridScale; Collider2D obstacle = Physics2D.OverlapPoint(worldPosition, LayerMask.GetMask("Obstacle")); if (obstacle != null) { return false; } return true; } public GameObject GetNextSection() { if (loopRetrieveIndex == loopStoreIndex) { return null; } GameObject nextSection = roadTilesLoop[loopRetrieveIndex]; loopRetrieveIndex = (loopRetrieveIndex + 1) % roadTilesLoop.Length; return nextSection; } }
Leave a Comment