Danro/Assets/Resources/Scripts/EnemyController.cs
Danil Iarosh a5e1f85877 Changed PickableProjectile: physics, collider, recall behaviour
Refactored and documented files: GameManager, MainMenu
2025-09-10 17:14:46 +03:00

138 lines
3.9 KiB
C#

using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
public class EnemyController : MonoBehaviour
{
public GameObject playerObj;
public float viewDistance = 5f;
public float viewAngle = 60f;
public float moveSpeed = 4f;
public float acceleration = 10f;
[SerializeField] private LayerMask obstacleMask;
private Animator animator;
private Rigidbody2D rb;
private Vector2 targetVelocity = Vector2.zero;
void Start()
{
rb = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
playerObj = GameManager.Instance.PlayerObj;
if (playerObj == null)
{
playerObj = GameObject.FindGameObjectWithTag("Player");
}
}
void FixedUpdate()
{
if (!playerObj) return;
Vector2 playerCenter = (Vector2)playerObj.transform.position;
if (PlayerInSight())
{
Vector2 toPlayer = playerCenter - (Vector2)transform.position;
float dist = toPlayer.magnitude;
if (dist > 0.01f)
rb.linearVelocity = toPlayer / dist * moveSpeed;
else
rb.linearVelocity = Vector2.zero;
}
else
{
rb.linearVelocity = Vector2.MoveTowards(
rb.linearVelocity, Vector2.zero, acceleration * Time.fixedDeltaTime);
}
animator.SetFloat("Speed", Mathf.Abs(rb.linearVelocity.magnitude));
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.CompareTag("Player"))
{
Rigidbody2D playerRb = collision.collider.GetComponent<Rigidbody2D>();
PlayerController playerController = playerObj.GetComponent<PlayerController>();
if (playerRb == null) return;
Vector2 contactNormal = collision.GetContact(0).normal;
if (contactNormal.y < -0.5f)
{
playerRb.linearVelocity = new Vector2(playerRb.linearVelocity.x, 35f);
Die();
}
else
{
playerController.Die();
}
}
else if (collision.collider.CompareTag("Projectile")) Die();
}
private bool PlayerInSight()
{
if (!playerObj) return false;
Transform player = playerObj.transform;
Vector2 eyePos = new(rb.position.x, rb.position.y + 1.45f);
Vector2 toPlayer = (Vector2)player.position - eyePos;
float dist = toPlayer.magnitude;
if (dist > viewDistance) return false;
Vector2 forward = (Vector2)transform.right;
float cosHalf = Mathf.Cos(0.5f * viewAngle * Mathf.Deg2Rad);
float dot = Vector2.Dot(forward.normalized, toPlayer / Mathf.Max(dist, 1e-6f));
if (dot < cosHalf) return false;
int mask = obstacleMask;
mask &= ~(1 << gameObject.layer);
mask &= ~(1 << playerObj.layer);
Vector2 origin = eyePos + forward.normalized * 0.05f;
RaycastHit2D hit = Physics2D.Raycast(origin, toPlayer.normalized, dist, mask);
if (hit.collider != null) return false;
return true;
}
void Die()
{
Destroy(gameObject);
}
#if UNITY_EDITOR
private void OnDrawGizmos()
{
if (!playerObj) return;
Vector2 origin = new(rb.position.x, rb.position.y + 1.45f);
Vector2 forward = (Vector2)transform.right;
float half = viewAngle * 0.5f;
Vector2 edgeA = (Vector2)(Quaternion.Euler(0, 0, +half) * (Vector3)forward);
Vector2 edgeB = (Vector2)(Quaternion.Euler(0, 0, -half) * (Vector3)forward);
Gizmos.color = Color.yellow;
Gizmos.DrawLine(origin, origin + edgeA * viewDistance);
Gizmos.DrawLine(origin, origin + edgeB * viewDistance);
Gizmos.DrawWireSphere(origin, viewDistance);
Vector2 toPlayer = (Vector2)playerObj.transform.position - origin;
if (toPlayer.magnitude <= viewDistance)
{
Gizmos.color = Color.red;
Gizmos.DrawLine(origin, playerObj.transform.position);
}
}
#endif
}