using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.AI; using Random = UnityEngine.Random; [RequireComponent(typeof(NavMeshAgent))] [RequireComponent(typeof(NPC))] public class MovementController : MonoBehaviour { private Transform _firePointTransform; public int PointStartID { get; set; } public int PointEndID { get; private set; } public float FlagDistance { get; private set; } private const float UpdateFlagPositionDelay = 5; private const float UpdateReachedDestinationDelay = 5; [SerializeField] private NavMeshAgent navMeshAgent; [SerializeField] private GameObject flag; public float DistanceToGo { get; private set; } public float RemainingDistance => navMeshAgent.remainingDistance; public Vector3 Velocity => navMeshAgent.velocity; private Dictionary _idNavPointDict; private NPC _myNpc; private Settings _settings; private void Awake() { _settings = SettingsReader.Instance.GetSettings; navMeshAgent.speed = _settings.MovementSpeed; _idNavPointDict = MapManager.Instance.IDToNavPoint; _myNpc = GetComponent(); _firePointTransform = transform.GetChild(0); InvokeRepeating(nameof(UpdateFlagPosition), 0, UpdateFlagPositionDelay); InvokeRepeating(nameof(ReachedDestination), 0, UpdateReachedDestinationDelay); } private void OnDestroy() { CancelInvoke(nameof(UpdateFlagPosition)); CancelInvoke(nameof(ReachedDestination)); } private void Update() { if (ReachedDestination()) { _myNpc.ChangePointState(_idNavPointDict[PointStartID].navType == NavPointType.Cover ? NpcEnumState.InCover : NpcEnumState.InDirectPoint); } else { _myNpc.ChangeBodyState(NpcBodyState.Standing); _myNpc.ChangePointState(NpcEnumState.InRunning); } if (_myNpc.NpcBodyState.State == NpcBodyState.Crouching) navMeshAgent.speed = _settings.MovementSpeed / 2; else navMeshAgent.speed = _settings.MovementSpeed; } private void UpdateFlagPosition() { FlagDistance = (flag.transform.position - gameObject.transform.position).magnitude; } [Obsolete] public void MoveToRandomPoint() { GoToNextNavPoint(MapManager.Instance.NavPoints[Random.Range(0, MapManager.Instance.NavPoints.Count)]); } public List GetPointsCandidate() { return MapManager.Instance.NavPoints .Where(point => (transform.position - point.Position).magnitude < _settings.MovementDistance) .ToList(); } public void GoToNextNavPoint(NavPoint destination) { if (navMeshAgent.isStopped == true) navMeshAgent.isStopped = false; PointStartID = PointEndID; PointEndID = destination.PointId; navMeshAgent.SetDestination(destination.Position); DistanceToGo = navMeshAgent.remainingDistance; } public void ReturnToStartPoint() { if (navMeshAgent.isStopped == true) navMeshAgent.isStopped = false; navMeshAgent.SetDestination(_idNavPointDict[PointStartID].Position); (PointEndID, PointStartID) = (PointStartID, PointEndID); } public void StopOnPath() { navMeshAgent.isStopped = true; } public bool ReachedDestination() { if (navMeshAgent.remainingDistance < 0.1f) { PointStartID = PointEndID; return true; } return false; } }