geometry-tower-defense/Assets/GameMain/Scripts/Entity/EntityLogic/EnemyEntity.cs

134 lines
3.9 KiB
C#

using Components;
using System.Collections.Generic;
using GeometryTD.Entity.EntityData;
using UnityEngine;
namespace GeometryTD.Entity
{
public class EnemyEntity : EntityBase
{
private const float WaypointReachDistance = 0.05f;
private Transform _target;
private float _speed;
private MovementComponent _movementComponent;
private readonly List<Vector3> _pathPoints = new List<Vector3>();
private int _pathPointIndex;
private bool _isDespawnRequested;
protected override void OnInit(object userData)
{
base.OnInit(userData);
_movementComponent = GetComponent<MovementComponent>();
}
protected override void OnShow(object userData)
{
base.OnShow(userData);
_target = null;
_pathPoints.Clear();
_pathPointIndex = 0;
_isDespawnRequested = false;
if (userData is EnemyData enemyData)
{
_speed = enemyData.Speed;
_target = enemyData.Player;
if (enemyData.HasPath)
{
IReadOnlyList<Vector3> pathPoints = enemyData.PathPoints;
for (int i = 0; i < pathPoints.Count; i++)
{
_pathPoints.Add(pathPoints[i]);
}
}
}
_movementComponent.OnInit(_speed, CachedTransform);
_movementComponent.SetMove(true);
}
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(elapseSeconds, realElapseSeconds);
if (_pathPoints.Count > 0)
{
UpdatePathMovement(elapseSeconds, realElapseSeconds);
return;
}
}
protected override void OnHide(bool isShutdown, object userData)
{
_movementComponent.SetMove(false);
_pathPoints.Clear();
_pathPointIndex = 0;
_isDespawnRequested = false;
base.OnHide(isShutdown, userData);
}
private void UpdatePathMovement(float elapseSeconds, float realElapseSeconds)
{
if (_isDespawnRequested)
{
return;
}
if (_pathPointIndex >= _pathPoints.Count)
{
DespawnOnReachHouse();
return;
}
Vector3 direction = GetDirectionToPathPoint(_pathPoints[_pathPointIndex], out float distanceSquared);
if (distanceSquared <= WaypointReachDistance * WaypointReachDistance)
{
_pathPointIndex++;
if (_pathPointIndex >= _pathPoints.Count)
{
DespawnOnReachHouse();
return;
}
direction = GetDirectionToPathPoint(_pathPoints[_pathPointIndex], out _);
}
if (direction.sqrMagnitude <= Mathf.Epsilon)
{
_movementComponent.SetMove(false);
return;
}
_movementComponent.SetMove(true);
_movementComponent.SetDirection(direction);
_movementComponent.OnUpdate(elapseSeconds, realElapseSeconds);
}
private Vector3 GetDirectionToPathPoint(Vector3 worldPoint, out float distanceSquared)
{
Vector3 delta = worldPoint - CachedTransform.position;
distanceSquared = delta.sqrMagnitude;
if (distanceSquared <= Mathf.Epsilon)
{
return Vector3.zero;
}
return delta.normalized;
}
private void DespawnOnReachHouse()
{
if (_isDespawnRequested)
{
return;
}
_isDespawnRequested = true;
_movementComponent.SetMove(false);
GameEntry.Entity.HideEntity(Entity);
}
}
}