ProjectZ/Assets/Scripts/Characters/Enemy/EnemyController.cs

277 lines
7.8 KiB
C#
Raw Normal View History

2024-02-19 21:00:36 +03:00
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using Mirror;
using UnityEngine.Animations.Rigging;
using Player;
public partial class EnemyController : Pawn
{
public bool spawnCube = false;
public NavMeshAgent controller;
public Animator animator;
public Rig targetLayer;
public AudioSource audioSource;
public ParticleSystem hitVFX;
public bool hasPath;
public GameObject propPrefab;
public Transform aimTarget;
public float aggressionDistance = 5f;
public float _stepTiming = 0.15f;
CustomNetworkManager networkManager;
NetworkGameManager networkGameManager;
private Transform _target = null;
private List<Pawn> players;
private Vector3 _position;
private float _stepCycle;
private float _runSpeed = 4.974f; //_walkSpeed = 0.299f
private float targetLayerWeight;
private int _currenPointId;
[SyncVar]
private float layerWeight;
private float _remainingDistance;
NavMeshTriangulation navMeshData;
[SyncVar(hook = nameof(OnStateChanged))]
private ENEMY_STATE state = ENEMY_STATE.PATROL;
2024-03-17 00:00:54 +03:00
2024-02-19 21:00:36 +03:00
private AudioClip skrClip, agressiveClip;
2024-03-17 00:00:54 +03:00
public NavMeshPath navMeshPath;
public bool isKilling = false;
[SerializeField] private bool canAttack = true;
2024-03-17 01:22:01 +03:00
2024-02-19 21:00:36 +03:00
void Start()
{
// Time.timeScale = 10;
skrClip = Resources.Load<AudioClip>("Audio/EnemySounds/woodSkr");
agressiveClip = Resources.Load<AudioClip>("Audio/EnemySounds/FX/agressive2");
networkManager = NetworkManager.singleton.GetComponent<CustomNetworkManager>();
networkGameManager = NetworkGameManager.singleton;
players = networkManager.alive;
if (!isServer) return;
this.OnDamage += TakeDamageAnimation;
navMeshData = NavMesh.CalculateTriangulation();
if (spawnCube)
{
Vector3 randLoc = navMeshData.vertices[navMeshData.indices[Random.Range(0, navMeshData.indices.Length - 3)]];
GameObject gameObject = Instantiate(propPrefab, randLoc + Vector3.up * 1, Quaternion.identity);
gameObject.GetComponent<PropBehaviour>().Original = true;
NetworkServer.Spawn(gameObject);
}
navMeshPath = new NavMeshPath();
}
void Update()
{
controller.speed = _speedMul * _runSpeed;
CalculateFootstepTriggers();
layerWeight = isServer ? Mathf.Lerp(layerWeight, targetLayerWeight, Time.deltaTime) : layerWeight;
targetLayer.weight = layerWeight;
if (!isServer) return;
animator.SetFloat("speed", controller.velocity.magnitude);
_remainingDistance = controller.GetPathRemainingDistance();
hasPath = controller.pathStatus != NavMeshPathStatus.PathComplete;
2024-03-17 01:22:01 +03:00
// if (controller.pathStatus == NavMeshPathStatus.PathComplete && !controller.pathPending && _target != null)
// {
// _target = null;
// }
2024-02-19 21:00:36 +03:00
// Есть таргет?
if (_target != null) // Да
{
controller.destination = _target.position;
float distance = Vector3.Distance(_target.transform.position, transform.position);
2024-03-17 01:22:01 +03:00
if (distance < aggressionDistance)
2024-02-19 21:00:36 +03:00
{
aimTarget.position = _target.position + _target.up * 1.2f;
targetLayerWeight = 1f;
2024-03-17 01:22:01 +03:00
2024-02-19 21:00:36 +03:00
if (distance < 1f)
{
2024-03-17 00:00:54 +03:00
if (canAttack && !isKilling)
2024-02-19 21:00:36 +03:00
{
RpcKillPlayer(_target);
animator.SetTrigger("attack");
StartCoroutine(AfterKillTimer());
}
}
}
else
{
_target = null;
}
}
else
{
targetLayerWeight = 0f;
// Ищем ближайшего игрока
foreach (var player in players)
{
float distance = Vector3.Distance(player.transform.position, transform.position);
if (distance <= aggressionDistance && CalculateNewPath(player.transform)) // && _remainingDistance > 0
{
//if (_remainingDistance < aggressionDistance && controller.GetPathRemainingDistance() >= 0)
_target = player.transform;
break;
}
}
if (_target == null && _remainingDistance <= 1.5f) //!controller.pathPending ||
{
SetRandomDestination();
}
}
}
bool CalculateNewPath(Transform target)
{
controller.CalculatePath(target.position, navMeshPath);
if (navMeshPath.status != NavMeshPathStatus.PathComplete)
{
return false;
2024-03-17 00:00:54 +03:00
}
return true;
2024-02-19 21:00:36 +03:00
}
[ClientRpc]
void RpcKillPlayer(Transform target)
{
Interactions interactions = target.GetComponent<Interactions>();
if (interactions != null) interactions.DropProp();
target.GetComponent<Pawn>().Die();
}
IEnumerator AfterKillTimer()
{
2024-03-17 00:00:54 +03:00
isKilling = true;
2024-02-19 21:00:36 +03:00
_target = null;
2024-03-17 01:02:25 +03:00
_speedMul = 0;
2024-03-17 00:00:54 +03:00
yield return new WaitForSeconds(7);
2024-03-17 01:02:25 +03:00
_speedMul = 1;
2024-03-17 00:00:54 +03:00
isKilling = false;
2024-02-19 21:00:36 +03:00
aimTarget.position = transform.position;
SetRandomDestination();
}
[Server]
void SetRandomDestination()
{
var targetPoint = GetRandomLocation();
// var targetPoint = navMeshData.vertices[2000];
//_patrolPoints[Random.Range(0, _patrolPoints.Length - 1)].position;
// hasPath = controller.SetDestination(targetPoint);
controller.destination = targetPoint;
// hasPath = controller.hasPath;
}
void OnStateChanged(ENEMY_STATE oldState, ENEMY_STATE newState)
{
audioSource.Stop();
switch (newState)
{
case ENEMY_STATE.PATROL:
audioSource.reverbZoneMix = 1f;
break;
case ENEMY_STATE.ROTATE:
audioSource.clip = skrClip;
audioSource.Play();
break;
case ENEMY_STATE.CHASE:
// audioSource.clip = agressiveClip;
// audioSource.reverbZoneMix = 0f;
// audioSource.Play();
break;
}
}
private List<Vector3> _points = new List<Vector3>();
Vector3 GetRandomLocation()
{
var point = navMeshData.vertices[navMeshData.indices[Random.Range(0, navMeshData.indices.Length - 3)]];
_points.Add(point);
return point;
}
void OnDrawGizmos()
{
foreach (var point in _points)
{
Gizmos.DrawSphere(point, 1f);
}
}
void CalculateFootstepTriggers()
{
float _velocity = ((_position - transform.position) / Time.deltaTime).magnitude;
// Debug.Log(_controllerVelocity);
float clampedVelocity = Mathf.Clamp(_runSpeed / _velocity + 1, 1, _runSpeed);
if (Time.time > _stepCycle && _velocity > 0)
{
CallFootstepClip();
_stepCycle = Time.time + (clampedVelocity * _stepTiming);
}
_position = transform.position;
}
public void CallFootstepClip()
{
audioSource.pitch = 1f + Random.Range(-0.1f, 0.1f);
audioSource.PlayOneShot(Resources.Load<AudioClip>("Audio/EnemySounds/Steps/monsterStep1"));
}
void TakeDamageAnimation(Pawn self)
{
2024-03-17 01:26:13 +03:00
print(this.name + " taken damage epta");
2024-03-17 00:00:54 +03:00
canAttack = false;
2024-03-17 01:02:25 +03:00
_speedMul = 0;
2024-02-19 21:00:36 +03:00
animator.SetTrigger("damage");
hitVFX.Stop();
hitVFX.Play();
2024-03-17 00:00:54 +03:00
StartCoroutine(AfterTakeDamage());
}
IEnumerator AfterTakeDamage()
{
2024-03-17 01:02:25 +03:00
yield return new WaitForSeconds(6);
_speedMul = 1;
2024-03-17 00:00:54 +03:00
canAttack = true;
2024-02-19 21:00:36 +03:00
}
2024-03-17 00:00:54 +03:00
}