using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine; using Utility; public class Zombie : MonoBehaviour { [SerializeField] List Noises; [SerializeField] private float _speed = 0.5f; [SerializeField] private float _rotateSpeed = 180.0f; [SerializeField] private float _attackRange = 1.3f; [SerializeField] private float _jumpForce; [SerializeField] private float _idleThresholdFactor = 0.2f; [SerializeField] private float _noiseDelay = 5.0f; [SerializeField, ShowOnly] private float _noiseTimer; [SerializeField] private LayerMask _groundLayer; private Rigidbody _rb; private AudioSource _audioSource; private bool _fadeOutNoise = false; private Animator _animator; private bool _isAttacking = false; private float _idleThreshold; private Vector3 _initialPosition; [ContextMenu("Kill Zombie")] private void TestDIe() { Die(); } void Start() { _rb = GetComponent(); _noiseTimer = Random.Range(0.3f * _noiseDelay, 1.5f * _noiseDelay); _audioSource = GetComponent(); _animator = GetComponent(); _idleThreshold = _speed / _idleThresholdFactor; _initialPosition = transform.position; } void Update() { //_idleThreshold = _speed / _idleThresholdFactor; UpdateNoise(); if (!_isAttacking) { MoveTowardsPlayer(); } } private void MoveTowardsPlayer() { Vector3 direction = (GameManager.Instance.Player.transform.position - transform.position); Quaternion goalRotation = Quaternion.LookRotation(direction); transform.rotation = Quaternion.Euler(0, Quaternion.RotateTowards(transform.rotation, goalRotation, _rotateSpeed * Time.deltaTime).eulerAngles.y, 0); float diff = direction.magnitude; //Debug.Log(diff); if (diff <= _attackRange && !_isAttacking) { _animator.SetFloat("Running", 0); _animator.SetBool("Idle", false); StartCoroutine(Attack()); } else { Vector3 oldPosition = _rb.position; Vector3 goalDirection = new Vector3(direction.x, 0.2f, direction.z); if (Physics.Raycast(transform.position + new Vector3(0, 0.1f, 0), goalDirection, 1f, _groundLayer)) { Debug.Log("RayCast HIT"); //_rb.AddForce(Vector3.up * _jumpForce, ForceMode.Impulse); _rb.MovePosition(_rb.position - transform.forward * Time.deltaTime); _rb.MovePosition(_rb.position + new Vector3(0, _jumpForce, 0) * Time.deltaTime); } _rb.MovePosition(_rb.position + goalDirection * _speed * Time.deltaTime); float dist = Vector3.Distance(oldPosition, _rb.position); //Debug.Log($"Distance: {dist}, Threshold: {_idleThreshold * Time.deltaTime}"); if (dist > _idleThreshold * Time.deltaTime) { _animator.SetBool("Idle", false); _animator.SetFloat("Running", _speed * 3.0f); } else { _animator.SetFloat("Running", 0); _animator.SetBool("Idle", true); } } } private IEnumerator Attack() { _isAttacking = true; _animator.SetBool("Attack", true); yield return new WaitForSeconds(0.5f); _animator.SetBool("Attack", false); // check if actually hit Vector3 direction = (GameManager.Instance.Player.transform.position - transform.position); float diff = direction.magnitude; if (diff <= _attackRange + 0.6f) { GameManager.Instance.Player.GetComponent().Hurt(); } _isAttacking = false; } private void UpdateNoise() { if (!_fadeOutNoise) { _noiseTimer -= Time.deltaTime; if (_noiseTimer < 0) { _noiseTimer = _noiseDelay; PlayRandomNoise(); } } else { _audioSource.volume -= _audioSource.volume * Time.deltaTime; } } private void PlayRandomNoise() { if (!_audioSource.isPlaying) { _audioSource.clip = Noises[Random.Range(0, Noises.Count)]; _audioSource.Play(); } } private void Die() { GameObject particleEffect = Instantiate(GameManager.Instance.ZombieDeathByDisableParticleEffect, transform.position, Quaternion.Euler(-90, 0, 0), GameManager.Instance.transform); AudioSource audio = particleEffect.GetComponent(); audio.clip = GetComponentInParent().ZombieDeathByDisableSoundeffects[Random.Range(0, GetComponentInParent().ZombieDeathByDisableSoundeffects.Count)]; audio.Play(); Destroy(gameObject); } public void FadeOutNoise() { _fadeOutNoise = true; } }