using UnityEngine; using TMPro; using UnityEngine.UI; using UnityEngine.SceneManagement; using System.Collections; public class TowerHealth : MonoBehaviour { public int maxHealth = 100; public GameObject floatingTextPrefab; [Header("HUD")] public Image healthFill; public TextMeshProUGUI healthText; public Color highHealthColor = new Color(0.18f, 0.88f, 0.42f); public Color lowHealthColor = new Color(0.95f, 0.22f, 0.18f); private int currentHealth; private bool isDead; private SpriteRenderer spriteRenderer; void Start() { currentHealth = maxHealth; spriteRenderer = GetComponent(); if (spriteRenderer != null) { spriteRenderer.color = Color.white; } EnsureHealthBar(); UpdateHealthBar(); } public void TakeDamage(int damage) { if (isDead) return; currentHealth -= damage; if (currentHealth < 0) currentHealth = 0; ShowFloatingDamage(damage); UpdateHealthBar(); if (currentHealth <= 0) { isDead = true; ShowStageLostScreen(); } } void UpdateHealthBar() { float healthPercentage = maxHealth <= 0 ? 0f : (float)currentHealth / maxHealth; if (healthFill != null) { healthFill.fillAmount = 1f; healthFill.color = Color.Lerp(lowHealthColor, highHealthColor, healthPercentage); RectTransform fillRect = healthFill.rectTransform; fillRect.anchorMax = new Vector2(healthPercentage, fillRect.anchorMax.y); fillRect.offsetMax = Vector2.zero; } if (healthText != null) { healthText.text = $"{currentHealth}/{maxHealth}"; } } void EnsureHealthBar() { if (healthFill != null && healthText != null) return; Canvas canvas = FindAnyObjectByType(); if (canvas == null) { GameObject canvasObject = new GameObject("GameUI", typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster)); canvas = canvasObject.GetComponent(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; CanvasScaler scaler = canvasObject.GetComponent(); scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; scaler.referenceResolution = new Vector2(800f, 600f); scaler.matchWidthOrHeight = 0.5f; } Transform existing = canvas.transform.Find("TowerHealthBar"); RectTransform container = existing != null ? existing.GetComponent() : CreateRect("TowerHealthBar", canvas.transform); container.anchorMin = new Vector2(1f, 1f); container.anchorMax = new Vector2(1f, 1f); container.pivot = new Vector2(1f, 1f); container.anchoredPosition = new Vector2(-24f, -24f); container.sizeDelta = new Vector2(240f, 54f); Image panel = container.GetComponent(); if (panel == null) panel = container.gameObject.AddComponent(); panel.color = new Color(0.05f, 0.06f, 0.08f, 0.84f); TextMeshProUGUI label = container.Find("Label")?.GetComponent(); if (label == null) { label = CreateText("Label", container, "TOWER", 14f); RectTransform labelRect = label.rectTransform; labelRect.anchorMin = new Vector2(0f, 1f); labelRect.anchorMax = new Vector2(0f, 1f); labelRect.pivot = new Vector2(0f, 1f); labelRect.anchoredPosition = new Vector2(12f, -7f); labelRect.sizeDelta = new Vector2(90f, 18f); } if (healthText == null) { healthText = container.Find("Value")?.GetComponent(); if (healthText == null) { healthText = CreateText("Value", container, "", 14f); healthText.alignment = TextAlignmentOptions.Right; RectTransform textRect = healthText.rectTransform; textRect.anchorMin = new Vector2(1f, 1f); textRect.anchorMax = new Vector2(1f, 1f); textRect.pivot = new Vector2(1f, 1f); textRect.anchoredPosition = new Vector2(-12f, -7f); textRect.sizeDelta = new Vector2(100f, 18f); } } RectTransform track = container.Find("Track")?.GetComponent(); if (track == null) { track = CreateRect("Track", container); track.anchorMin = new Vector2(0f, 0f); track.anchorMax = new Vector2(1f, 0f); track.pivot = new Vector2(0.5f, 0f); track.anchoredPosition = new Vector2(0f, 10f); track.sizeDelta = new Vector2(-24f, 16f); Image trackImage = track.gameObject.AddComponent(); trackImage.color = new Color(0.16f, 0.17f, 0.2f, 1f); } if (healthFill == null) { healthFill = track.Find("Fill")?.GetComponent(); if (healthFill == null) { RectTransform fill = CreateRect("Fill", track); fill.anchorMin = Vector2.zero; fill.anchorMax = Vector2.one; fill.offsetMin = Vector2.zero; fill.offsetMax = Vector2.zero; healthFill = fill.gameObject.AddComponent(); healthFill.type = Image.Type.Filled; healthFill.fillMethod = Image.FillMethod.Horizontal; healthFill.fillOrigin = (int)Image.OriginHorizontal.Left; } } healthFill.type = Image.Type.Simple; } void ShowStageLostScreen() { Time.timeScale = 0f; Canvas canvas = FindAnyObjectByType(); if (canvas == null) return; GameObject overlay = new GameObject("StageLostOverlay", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image)); RectTransform rect = overlay.GetComponent(); rect.SetParent(canvas.transform, false); rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.offsetMin = Vector2.zero; rect.offsetMax = Vector2.zero; rect.SetAsLastSibling(); Image background = overlay.GetComponent(); background.color = new Color(0f, 0f, 0f, 0.8f); background.raycastTarget = true; TextMeshProUGUI title = CreateText("Title", rect, "STAGE LOST", 44f); title.alignment = TextAlignmentOptions.Center; PlaceOverlayRect(title.rectTransform, 0f, 64f, 420f, 68f); TextMeshProUGUI subtitle = CreateText("Subtitle", rect, "Wave progress and upgrades were lost.", 19f); subtitle.fontStyle = FontStyles.Normal; subtitle.alignment = TextAlignmentOptions.Center; PlaceOverlayRect(subtitle.rectTransform, 0f, 12f, 520f, 42f); Button menuButton = CreateOverlayButton("MenuButton", rect, "MAIN MENU", ReturnToMenu); PlaceOverlayRect(menuButton.GetComponent(), 0f, -64f, 220f, 54f); StartCoroutine(ReturnToMenuAfterDelay()); } IEnumerator ReturnToMenuAfterDelay() { yield return new WaitForSecondsRealtime(2.25f); ReturnToMenu(); } void ReturnToMenu() { Time.timeScale = 1f; SceneManager.LoadScene("MainMenu"); } static RectTransform CreateRect(string name, Transform parent) { GameObject obj = new GameObject(name, typeof(RectTransform)); RectTransform rect = obj.GetComponent(); rect.SetParent(parent, false); return rect; } static TextMeshProUGUI CreateText(string name, Transform parent, string text, float fontSize) { GameObject obj = new GameObject(name, typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI)); RectTransform rect = obj.GetComponent(); rect.SetParent(parent, false); TextMeshProUGUI label = obj.GetComponent(); label.text = text; label.fontSize = fontSize; label.fontStyle = FontStyles.Bold; label.color = new Color(0.92f, 0.95f, 1f, 1f); label.raycastTarget = false; return label; } static Button CreateOverlayButton(string name, Transform parent, string label, UnityEngine.Events.UnityAction onClick) { GameObject obj = new GameObject(name, typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button)); RectTransform rect = obj.GetComponent(); rect.SetParent(parent, false); Image image = obj.GetComponent(); image.color = new Color(0.18f, 0.5f, 0.74f, 1f); Button button = obj.GetComponent