You've already forked zumbi-game
138 lines
3.9 KiB
C#
138 lines
3.9 KiB
C#
using UnityEngine;
|
|
|
|
[RequireComponent(typeof(Animator))]
|
|
[RequireComponent(typeof(Rigidbody))]
|
|
[RequireComponent(typeof(AudioSource))]
|
|
public class ZombieController : MonoBehaviour
|
|
{
|
|
private static readonly int DieHash = Animator.StringToHash("Die");
|
|
private static readonly int IsAttackingHash = Animator.StringToHash("isAttacking");
|
|
private static readonly int IsWalkingHash = Animator.StringToHash("isWalking");
|
|
private static readonly int IsRunningHash = Animator.StringToHash("isRunning");
|
|
|
|
[Header("Health")]
|
|
private readonly float maxHealth = 50;
|
|
private float currentHealth;
|
|
|
|
[Header("Movement")]
|
|
private readonly float walkSpeed = 1f;
|
|
private readonly float runSpeed = 2f;
|
|
private readonly float runDistance = 5f; // od kedy začne bežať
|
|
private readonly float attackDistance = 1.5f; // od kedy útočí
|
|
|
|
[Header("Attack")]
|
|
private readonly float attackDamage = 10f;
|
|
private readonly float attackCooldown = 1f;
|
|
private float lastAttackTime;
|
|
|
|
[Header("Sounds")]
|
|
[SerializeField] private AudioClip[] sfx;
|
|
[SerializeField] private int sfxDelay = 5; // seconds
|
|
|
|
private PlayerController player;
|
|
private Animator animator;
|
|
private AudioSource audioSource;
|
|
private float lastSfxPlay;
|
|
|
|
private bool IsDead() => currentHealth == 0;
|
|
|
|
private void Start()
|
|
{
|
|
currentHealth = maxHealth;
|
|
animator = GetComponent<Animator>();
|
|
player = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>();
|
|
audioSource = GetComponent<AudioSource>();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (IsDead()) return;
|
|
|
|
PlaySfx();
|
|
|
|
float distance = Vector3.Distance(transform.position, player.transform.position);
|
|
|
|
if (distance <= attackDistance)
|
|
{
|
|
StopMoving();
|
|
TryAttack();
|
|
}
|
|
else if (distance <= runDistance)
|
|
{
|
|
MoveToPlayer(runSpeed);
|
|
animator.SetBool(IsRunningHash, true);
|
|
animator.SetBool(IsWalkingHash, false);
|
|
animator.SetBool(IsAttackingHash, false);
|
|
}
|
|
else
|
|
{
|
|
MoveToPlayer(walkSpeed);
|
|
animator.SetBool(IsWalkingHash, true);
|
|
animator.SetBool(IsRunningHash, false);
|
|
animator.SetBool(IsAttackingHash, false);
|
|
}
|
|
}
|
|
|
|
private AudioClip PickSfx()
|
|
{
|
|
return sfx[Random.Range(0, sfx.Length)];
|
|
}
|
|
|
|
private void PlaySfx()
|
|
{
|
|
if (Time.time - lastSfxPlay <= sfxDelay)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var clip = PickSfx();
|
|
audioSource.PlayOneShot(clip);
|
|
lastSfxPlay = Time.time;
|
|
}
|
|
|
|
private void MoveToPlayer(float speed)
|
|
{
|
|
Vector3 direction = (player.transform.position - transform.position).normalized;
|
|
transform.position += speed * Time.deltaTime * direction;
|
|
transform.LookAt(new Vector3(player.transform.position.x, transform.position.y, player.transform.position.z));
|
|
}
|
|
|
|
private void StopMoving()
|
|
{
|
|
animator.SetBool(IsWalkingHash, false);
|
|
animator.SetBool(IsRunningHash, false);
|
|
}
|
|
|
|
private void TryAttack()
|
|
{
|
|
animator.SetBool(IsAttackingHash, true);
|
|
|
|
if (Time.time - lastAttackTime >= attackCooldown)
|
|
{
|
|
lastAttackTime = Time.time;
|
|
Debug.Log($"{gameObject.name} attacked player by {attackDamage} damage");
|
|
// player.GetComponent<PlayerHealth>()?.TakeDamage(attackDamage);
|
|
}
|
|
}
|
|
|
|
public void TakeDamage(float amount)
|
|
{
|
|
if (IsDead()) return;
|
|
|
|
currentHealth -= amount;
|
|
Debug.Log($"{gameObject.name} took {amount} damage. HP: {currentHealth}/{maxHealth}");
|
|
|
|
if (currentHealth <= 0)
|
|
Die();
|
|
}
|
|
|
|
private void Die()
|
|
{
|
|
Debug.Log($"{gameObject.name} is dead");
|
|
|
|
animator.SetTrigger(DieHash);
|
|
player.IncrementKills();
|
|
|
|
Destroy(gameObject, 2f);
|
|
}
|
|
} |