Files
PGiZ3/Assets/Code/Gameplay/Enemy/SimpleEnemy.cs
T
2026-02-24 10:32:41 +03:00

161 lines
5.1 KiB
C#

using Code.Gameplay.Character.Core;
using UnityEngine;
using Code.Gameplay.Core;
using Code.Gameplay.Character.Stats;
using Code.Gameplay.Weapons;
namespace Code.Gameplay.Enemy
{
public class SimpleEnemy : MonoBehaviour, IDamageable
{
[SerializeField] private HealthSystem healthSystem;
[SerializeField] private WeaponBase weapon;
[SerializeField] private Transform weaponPoint;
[SerializeField] private Transform firePoint;
[SerializeField] private Transform target;
[SerializeField] private float moveSpeed = 3f;
[SerializeField] private float rotationSpeed = 5f;
[SerializeField] private float detectionRange = 20f;
[SerializeField] private float attackRange = 15f;
[SerializeField] private float stopDistance = 5f;
[SerializeField] private float attackCooldown = 1f;
[SerializeField] private LayerMask obstacleMask;
private float lastAttackTime;
private bool isAttacking;
private CharacterController characterController;
public bool IsAlive => healthSystem != null && healthSystem.IsAlive;
private void Awake()
{
characterController = GetComponent<CharacterController>();
if (characterController == null)
characterController = gameObject.AddComponent<CharacterController>();
if (healthSystem == null)
healthSystem = GetComponent<HealthSystem>();
}
private void Start()
{
if (weapon)
{
var weaponGo = Instantiate(weapon.gameObject, weaponPoint);
weapon = weaponGo.GetComponent<WeaponBase>();
weapon._firePoint = firePoint.transform;
weapon.Reload();
attackCooldown = weapon.FireRate + 0.01f;
}
if (healthSystem != null)
{
healthSystem.OnDied += HandleDeath;
}
if (target != null) return;
var player = FindFirstObjectByType<CharacterProvider>();
if (player != null)
target = player.transform;
}
private void Update()
{
if (!IsAlive || !target) return;
var distanceToTarget = Vector3.Distance(transform.position, target.position);
if (!(distanceToTarget <= detectionRange)) return;
RotateTowardsTarget();
if (distanceToTarget <= attackRange)
{
Attack();
if (distanceToTarget < stopDistance)
{
MoveAway();
}
}
else
{
MoveTowardsTarget();
}
}
private void RotateTowardsTarget()
{
var direction = (target.position - transform.position).normalized;
direction.y = 0;
var lookRotation = Quaternion.LookRotation(direction);
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * rotationSpeed);
}
private void MoveTowardsTarget()
{
var direction = (target.position - transform.position).normalized;
direction.y = 0;
characterController.Move(direction * (moveSpeed * Time.deltaTime));
}
private void MoveAway()
{
var direction = (transform.position - target.position).normalized;
direction.y = 0;
characterController.Move(direction * (moveSpeed * Time.deltaTime));
}
private void Attack()
{
if (Time.time - lastAttackTime < attackCooldown) return;
if (!weapon) return;
if (!HasLineOfSight()) return;
lastAttackTime = Time.time;
if (weapon.CurrentAmmo <= 0)
weapon.Reload();
else
weapon.StartShooting();
}
private bool HasLineOfSight()
{
if (!target) return false;
var direction = (target.position - weaponPoint.position).normalized;
var distance = Vector3.Distance(weaponPoint.position, target.position);
if (Physics.Raycast(weaponPoint.position, direction, out var hit, distance, obstacleMask))
{
return hit.collider.transform == target;
}
return true;
}
private void HandleDeath()
{
enabled = false;
var healthGo = Instantiate(Resources.Load<GameObject>("Prefabs/HealthBuff").gameObject);
healthGo.transform.position = new Vector3(transform.position.x, transform.position.y - 1, transform.position.z);
Destroy(gameObject, 1);
}
public void TakeDamage(float damage)
{
healthSystem?.TakeDamage(damage);
}
public Transform GetTransform() => transform;
}
}