Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using AmazingAssets.AdvancedDissolve.Examples;
- using System.Collections;
- using System.Collections.Generic;
- using Unity.VisualScripting;
- using UnityEngine;
- using UnityEngine.AI;
- using UnityEngine.Assertions;
- public enum EnemyState
- {
- Moving,
- Attacking
- }
- [RequireComponent(typeof(NavMeshAgent))]
- [RequireComponent(typeof(Animator))]
- public abstract class EnemyNavMeshAgent : MonoBehaviour, IDamageable
- {
- [SerializeField] EnemyState _state = EnemyState.Moving;
- [SerializeField] Transform _start;
- [SerializeField] Transform _end;
- [SerializeField] PlayerAttackable _nearestTarget;
- protected Animator _animator;
- [SerializeField] float _health = 50f;
- NavMeshAgent _agent;
- bool _isDead = false;
- [SerializeField] float _deathDelay = 0.5f;
- public void Damage(float damage)
- {
- _health -= damage;
- if (_health <= 0 && !_isDead)
- {
- HandleDeath();
- }
- }
- private void HandleDeath()
- {
- _animator.SetTrigger("Die");
- _isDead = true;
- gameObject.layer = LayerMask.NameToLayer("Default");
- // Disable the colliders
- foreach (Collider collider in GetComponentsInChildren<Collider>())
- {
- collider.enabled = false;
- }
- _agent.isStopped = true;
- foreach (Renderer renderer in gameObject.GetComponentsInChildren<Renderer>())
- {
- AnimateCutoutAndDestroy script = gameObject.AddComponent<AnimateCutoutAndDestroy>();
- //Instantiate material and assign it to the script
- script.material = renderer.material;
- }
- }
- public bool IsDead()
- {
- return _isDead;
- }
- // Start is called before the first frame update
- void Start()
- {
- _agent = GetComponent<NavMeshAgent>();
- Assert.IsNotNull(_agent, "NavMeshAgent not set up!");
- transform.position = _start.position;
- _animator = GetComponent<Animator>();
- }
- // Update is called once per frame
- void Update()
- {
- if (IsDead())
- {
- return;
- }
- Debug.Log($"Agent: {_agent != null}", this);
- if (_nearestTarget == null)
- {
- // Try fetching one
- PlayerAttackable[] targets = GetTargets();
- float closestDistance = Mathf.Infinity;
- foreach (PlayerAttackable target in targets)
- {
- float distanceToTarget = Vector3.Distance(transform.position, target.gameObject.transform.position);
- if (distanceToTarget < closestDistance)
- {
- NavMeshPath path = new NavMeshPath();
- if (_agent.CalculatePath(target.transform.position, path) && path.status == NavMeshPathStatus.PathComplete)
- {
- // Do we allow partial paths? Might make sense for ranged attacks.
- _nearestTarget = target;
- closestDistance = distanceToTarget;
- }
- }
- }
- }
- _state = _nearestTarget == null ? EnemyState.Moving : EnemyState.Attacking;
- switch (_state) {
- case EnemyState.Moving:
- if (_agent && _end)
- {
- Debug.Log("Setting Destination as " + _end.position, this);
- _agent.SetDestination(_end.position);
- }
- break;
- case EnemyState.Attacking:
- _agent.SetDestination(_nearestTarget.gameObject.transform.position);
- PerformAttack(_nearestTarget);
- break;
- }
- _animator.SetFloat("Speed", _agent.velocity.magnitude);
- }
- protected abstract void PerformAttack(PlayerAttackable nearestTarget);
- protected abstract PlayerAttackable[] GetTargets();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement