Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.AI;
- [RequireComponent(typeof(NavMeshAgent))]
- public class EnemyController : MonoBehaviour {
- enum EnemyState {
- Idle, // просто стоїть
- Pursuit, // переслідує ціль
- Battle // атакує
- }
- public Transform aimPoint;
- public Inventory inventory;
- public float aggroDistance;
- public float alertDistance;
- private NavMeshAgent agent;
- private EnemyState state;
- private Vector3 lastPlayerSeenLocation;
- private readonly RaycastHit[] _hits = new RaycastHit[10];
- private void Awake() {
- agent = GetComponent<NavMeshAgent>();
- lastPlayerSeenLocation = transform.position;
- }
- private void Update() {
- var playerLocation = PlayerController.Me.transform.position;
- bool playerSeenAtThisUpdate = false;
- state = EnemyState.Idle;
- // Якщо гравець в зоні бачення ворогу
- if (Vector3.Distance(aimPoint.position, PlayerController.Me.aimPoint.position) <= aggroDistance) {
- Vector3 direction = (PlayerController.Me.aimPoint.position - aimPoint.position).normalized;
- Ray ray = new Ray(aimPoint.position, direction);
- int hits = Physics.RaycastNonAlloc(ray, _hits, aggroDistance);
- Array.Sort(_hits, 0, hits, new RaycastHitComparer(ray.origin));
- // Якщо між ворогом і гравцем нема перешкод
- if (_hits[0].transform != null && CompareLayer(_hits[0].transform.gameObject, PlayerController.Me.playerLayer)) {
- playerSeenAtThisUpdate = true;
- // Ворог дивиться на гравця
- Vector3 lookPos = new Vector3(PlayerController.Me.aimPoint.position.x, transform.position.y, PlayerController.Me.aimPoint.position.z);
- transform.LookAt(lookPos);
- lastPlayerSeenLocation = playerLocation;
- state = EnemyState.Battle;
- } else
- state = EnemyState.Pursuit;
- } else if (Vector3.Distance(transform.position, lastPlayerSeenLocation) > 1f) {
- state = EnemyState.Pursuit;
- }
- if (state == EnemyState.Idle) {
- lastPlayerSeenLocation = transform.position; // загубив гравця
- agent.SetDestination(transform.position); // бот зупиняється
- if (inventory != null) // бот не атакує
- inventory.SetFiring(false);
- } else if (state == EnemyState.Pursuit) {
- agent.SetDestination(lastPlayerSeenLocation); // ворог йде туди, де він бачив гравця
- if (inventory != null) // бот не атакує
- inventory.SetFiring(false);
- if (playerSeenAtThisUpdate)
- NotifyOthers(playerLocation);
- } else { // battle
- agent.SetDestination(transform.position); // бот зупиняється
- if (inventory != null) // бот атакує
- inventory.SetFiring(true);
- if (playerSeenAtThisUpdate)
- NotifyOthers(playerLocation);
- }
- }
- private void NotifyOthers(Vector3 lastPlayerSeenLocation) {
- EnemyController[] allBots = FindObjectsOfType<EnemyController>();
- for (int i = 0; i < allBots.Length; i++) {
- if (allBots[i] != this && Vector3.Distance(transform.position, allBots[i].transform.position) <= alertDistance) {
- allBots[i].SayThatPlayerHasBeenInPosition(lastPlayerSeenLocation);
- }
- }
- }
- public void SayThatPlayerHasBeenInPosition(Vector3 lastPlayerSeenLocation) {
- this.lastPlayerSeenLocation = lastPlayerSeenLocation;
- }
- private void OnDrawGizmosSelected() {
- if (aimPoint != null) {
- Gizmos.color = new Color(0f, 1f, 1f, 0.2f);
- Gizmos.DrawSphere(aimPoint.position, aggroDistance);
- }
- var player = FindObjectOfType<PlayerController>();
- if (Physics.Linecast(aimPoint.position, player.aimPoint.position, out RaycastHit hit)) {
- Gizmos.color = Color.blue;
- Gizmos.DrawLine(aimPoint.position, player.aimPoint.position);
- }
- }
- private static bool CompareLayer(GameObject target, LayerMask layers) {
- return ((1 << target.layer) & layers) != 0;
- }
- }
- public class RaycastHitComparer : IComparer<RaycastHit> {
- private Vector3 origin;
- public RaycastHitComparer(Vector3 origin) {
- this.origin = origin;
- }
- public int Compare(RaycastHit x, RaycastHit y) {
- bool xIsValid = x.collider != null;
- bool yIsValid = y.collider != null;
- if (!xIsValid && !yIsValid)
- return 0;
- if (!xIsValid)
- return 1;
- if (!yIsValid)
- return -1;
- float distanceX = Vector3.Distance(origin, x.point);
- float distanceY = Vector3.Distance(origin, y.point);
- return distanceX.CompareTo(distanceY);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement