I’m trying to deal damage to my player when the enemy is at a given distance, but whatever I try the player’s life goes instantly to 0. I tried to add the StartCoroutine(ReduceHealthOverTime());
line in the player script and the slider and health are perfectly decreasing. I also tried different approaches, but the result is always the same.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class PlayerHealth : MonoBehaviour
{
[SerializeField] private float maxHealth = 100f;
[SerializeField] private float currentHealth = 100f;
[SerializeField] private Slider healthSlider;
private void Awake()
{
// Initialize health
currentHealth = maxHealth;
// Configure the slider
if (healthSlider != null)
{
healthSlider.minValue = 0f;
healthSlider.maxValue = 1f;
UpdateHealthUI();
}
// Start the coroutine to remove 1 health every second
//StartCoroutine(ReduceHealthOverTime());
}
public void SetHealth(float health)
{
currentHealth = Mathf.Clamp(health, 0f, maxHealth);
UpdateHealthUI();
}
public void TakeDamage(float damage)
{
Debug.Log($"Before damage: Health = {currentHealth}, Damage = {damage}");
currentHealth = Mathf.Max(0f, currentHealth - damage);
Debug.Log($"After damage: Health = {currentHealth}");
UpdateHealthUI();
}
public void Heal(float amount)
{
currentHealth = Mathf.Min(maxHealth, currentHealth + amount);
UpdateHealthUI();
}
private void UpdateHealthUI()
{
if (healthSlider != null)
{
// Convert current health to 0-1 range for the slider
healthSlider.value = currentHealth / maxHealth;
}
// Log the current health to see if slider is working
Debug.Log("Current Health: " + currentHealth + " (Slider Value: " + (healthSlider != null ? healthSlider.value.ToString() : "No Slider") + ")");
}
// Coroutine to reduce health by 1 every second
private IEnumerator ReduceHealthOverTime()
{
while (currentHealth > 0)
{
yield return new WaitForSeconds(1f);
TakeDamage(1f);
}
}
// Getters for current and max health
public float GetCurrentHealth() => currentHealth;
public float GetMaxHealth() => maxHealth;
}
using UnityEngine;
using Assets.FantasyMonsters.Common.Scripts;
using System.Collections;
public class EnemyMovement : MonoBehaviour
{
[Header("Movement Settings")]
[SerializeField] private float moveSpeed = 5f;
[SerializeField] private float baseStopDistance = 5f;
[SerializeField] private float stopDistanceVariation = 1.5f;
[SerializeField] private bool faceMovementDirection = true;
[Header("Attack Settings")]
[SerializeField] private float attackCooldown = 2f;
[SerializeField] private float normalAttackDamage = 10f;
[SerializeField] private float altAttackDamage = 20f;
[Header("References")]
[SerializeField] private Transform player;
[SerializeField] private bool debugMode = true;
private float actualStopDistance;
private Monster monsterScript;
private Animator animator;
private PlayerHealth playerHealth;
private bool canAttack = true;
private void Start()
{
// Initialize stop distance with random variation
actualStopDistance = baseStopDistance + Random.Range(-stopDistanceVariation, stopDistanceVariation);
// Get required components
monsterScript = GetComponent<Monster>();
animator = GetComponent<Animator>();
// Set up player reference and health component
if (player != null)
{
playerHealth = player.GetComponent<PlayerHealth>();
if (playerHealth == null && debugMode)
{
Debug.LogError("PlayerHealth component not found on player!");
}
}
// Check for required components
if (monsterScript == null && debugMode)
{
Debug.LogError("Monster component not found on enemy!");
}
if (animator == null && debugMode)
{
Debug.LogError("Animator component not found on enemy!");
}
}
private void Update()
{
if (player == null) return;
float distanceToPlayer = Vector3.Distance(transform.position, player.position);
if (distanceToPlayer > actualStopDistance)
{
// Move towards player
transform.Translate(Vector3.left * moveSpeed * Time.deltaTime);
// Handle rotation
if (faceMovementDirection)
{
transform.rotation = Quaternion.Euler(0, -90, 0);
}
// Update animation state
monsterScript?.SetState(MonsterState.Walk);
// Reset attack animation
if (animator != null)
{
animator.ResetTrigger("Attack");
}
}
else
{
// When in range, stop and attack
monsterScript?.SetState(MonsterState.Idle);
// Only try to attack if we can
if (canAttack && playerHealth != null)
{
StartCoroutine(Attack());
}
}
if (debugMode)
{
Debug.DrawLine(transform.position, transform.position + Vector3.left * actualStopDistance, Color.red);
}
}
private IEnumerator Attack()
{
if (!canAttack) yield break;
canAttack = false;
if (debugMode)
{
Debug.Log($"[{gameObject.name}] Starting attack");
}
// Play attack animation
if (animator != null)
{
animator.SetTrigger("Attack");
}
// Deal damage
if (playerHealth != null)
{
if (debugMode)
{
Debug.Log($"[{gameObject.name}] Dealing {normalAttackDamage} damage");
}
playerHealth.TakeDamage(normalAttackDamage);
}
// Wait for cooldown
yield return new WaitForSeconds(attackCooldown);
canAttack = true;
}
public void SetPlayer(Transform playerTransform)
{
player = playerTransform;
if (player != null)
{
playerHealth = player.GetComponent<PlayerHealth>();
}
}
private void OnDisable()
{
// Make sure we can attack when re-enabled
canAttack = true;
}
}
7