Files
PGiZ3/Assets/Code/Gameplay/Enemy/SimpleEnemy.cs
T
2026-02-23 20:16:07 +03:00

145 lines
4.3 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 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 (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 == null) 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 == null) return;
if (!HasLineOfSight()) return;
lastAttackTime = Time.time;
weapon.Shoot();
}
private bool HasLineOfSight()
{
if (target == null) return false;
var direction = (target.position - firePoint.position).normalized;
var distance = Vector3.Distance(firePoint.position, target.position);
if (Physics.Raycast(firePoint.position, direction, out var hit, distance, obstacleMask))
{
return hit.collider.transform == target;
}
return true;
}
private void HandleDeath()
{
enabled = false;
Destroy(gameObject, 2f);
}
public void TakeDamage(float damage)
{
healthSystem?.TakeDamage(damage);
}
public Transform GetTransform() => transform;
}
}