Files
PGiZ2/Assets/Code/Gameplay/Player/PlayerHealth.cs
T
2026-02-03 20:22:33 +03:00

120 lines
3.3 KiB
C#

using UnityEngine;
using System;
using Code.Gameplay.Enemies;
using UnityEngine.UI;
namespace Code.Gameplay.Player
{
public class PlayerHealth : MonoBehaviour
{
[SerializeField] private int _maxHealth = 100;
[SerializeField] private int _damageFromEnemy = 25;
[SerializeField] private float _invincibilityDuration = 2f;
[SerializeField] private float _attackCooldown = 0.5f;
[SerializeField] private float _attackRange = 2f;
[SerializeField] private LayerMask _enemyLayer;
[SerializeField] private Slider _healthBar;
[SerializeField] private AudioSource audioSource;
private int _currentHealth;
private bool _isInvincible;
private float _invincibilityTimer;
private float _lastAttackTime;
public float nextAttackTime => _lastAttackTime + _attackCooldown;
private AudioClip _attackClip;
public event Action<int> OnHealthChanged;
public event Action OnDied;
public event Action OnTookDamage;
public event Action OnAttacked;
public bool IsAlive => _currentHealth > 0;
public bool CanTakeDamage => !_isInvincible && IsAlive;
private void Start()
{
_attackClip = Resources.Load<AudioClip>("Audio/SFX/AttackSFX");
_currentHealth = _maxHealth;
OnHealthChanged?.Invoke(_currentHealth);
}
private void Update()
{
UpdateInvincibility();
_healthBar.value = (float)_currentHealth / _maxHealth;
}
public void TakeDamage(bool fatal = false)
{
if (!CanTakeDamage) return;
if (fatal)
_currentHealth = 0;
else
_currentHealth -= _damageFromEnemy;
OnHealthChanged?.Invoke(_currentHealth);
OnTookDamage?.Invoke();
if (_currentHealth <= 0)
{
Die();
return;
}
StartInvincibility();
}
public void TryAttack()
{
if (Time.time < nextAttackTime) return;
_lastAttackTime = Time.time;
OnAttacked?.Invoke();
audioSource.PlayOneShot(_attackClip);
var hits = Physics2D.OverlapCircleAll(transform.position, _attackRange, _enemyLayer);
foreach (var hit in hits)
{
if (hit.TryGetComponent(out IEnemy enemy))
{
enemy.TakeDamage();
}
}
}
private void StartInvincibility()
{
_isInvincible = true;
_invincibilityTimer = _invincibilityDuration;
}
private void UpdateInvincibility()
{
if (!_isInvincible) return;
_invincibilityTimer -= Time.deltaTime;
if (_invincibilityTimer <= 0f)
{
_isInvincible = false;
}
}
private void Die()
{
_healthBar.value = 0;
OnDied?.Invoke();
enabled = false;
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, _attackRange);
}
}
}