using UnityEngine; using BehaviorDesigner.Runtime; using BehaviorDesigner.Runtime.Tasks.Movement; #if !(UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4) using UnityEngine.AI; #endif namespace Valheim { public abstract class NavMeshMovement2 : Movement { [Tooltip("The angular speed of the agent")] public SharedFloat angularSpeed = 120; [Tooltip("The agent has arrived when the destination is less than the specified amount")] // public SharedFloat arriveDistance = 0.2f; // [Tooltip("Should the NavMeshAgent be stopped when the task ends?")] public SharedBool stopOnTaskEnd = true; [Tooltip("Should the NavMeshAgent rotation be updated when the task ends?")] public SharedBool updateRotation = true; // Component references protected NavMeshAgent navMeshAgent; /// /// Cache the component references. /// public override void OnAwake() { navMeshAgent = GetComponent(); } /// /// Allow pathfinding to resume. /// public override void OnStart() { navMeshAgent.angularSpeed = angularSpeed.Value; #if UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4 || UNITY_5_5 navMeshAgent.Resume(); #else navMeshAgent.isStopped = false; #endif if (!updateRotation.Value) { UpdateRotation(true); } } /// /// Set a new pathfinding destination. /// /// The destination to set. /// True if the destination is valid. protected override bool SetDestination(Vector3 destination) { #if UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4 || UNITY_5_5 navMeshAgent.Resume(); #else navMeshAgent.isStopped = false; #endif return navMeshAgent.SetDestination(destination); } /// /// Specifies if the rotation should be updated. /// /// Should the rotation be updated? protected override void UpdateRotation(bool update) { navMeshAgent.updateRotation = update; } /// /// Does the agent have a pathfinding path? /// /// True if the agent has a pathfinding path. public virtual bool HasPath(float arriveDistance) { return navMeshAgent.hasPath && navMeshAgent.remainingDistance > arriveDistance; } /// /// Returns the velocity of the agent. /// /// The velocity of the agent. protected override Vector3 Velocity() { return navMeshAgent.velocity; } /// /// Returns true if the position is a valid pathfinding position. /// /// The position to sample. /// True if the position is a valid pathfinding position. protected bool SamplePosition(Vector3 position) { NavMeshHit hit; return NavMesh.SamplePosition(position, out hit, float.MaxValue, NavMesh.AllAreas); } /// /// Has the agent arrived at the destination? /// /// True if the agent has arrived at the destination. public virtual bool HasArrived(float arriveDistance) { // The path hasn't been computed yet if the path is pending. float remainingDistance; if (navMeshAgent.pathPending) { remainingDistance = float.PositiveInfinity; } else { remainingDistance = navMeshAgent.remainingDistance; } return remainingDistance <= arriveDistance; } /// /// Stop pathfinding. /// protected override void Stop() { UpdateRotation(updateRotation.Value); if (navMeshAgent.hasPath) { #if UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4 || UNITY_5_5 navMeshAgent.Stop(); #else navMeshAgent.isStopped = true; #endif } } /// /// The task has ended. Stop moving. /// public override void OnEnd() { if (stopOnTaskEnd.Value) { Stop(); } else { UpdateRotation(updateRotation.Value); } } /// /// The behavior tree has ended. Stop moving. /// public override void OnBehaviorComplete() { Stop(); } /// /// Reset the values back to their defaults. /// public override void OnReset() { angularSpeed = 120; stopOnTaskEnd = true; } } }