using System; using UnityEngine; using NodeCanvas.Framework; using ParadoxNotion.Design; using NavMeshAgent = UnityEngine.AI.NavMeshAgent; using NavMesh = UnityEngine.AI.NavMesh; using NavMeshHit = UnityEngine.AI.NavMeshHit; using Random = UnityEngine.Random; namespace NodeCanvas.Tasks.Actions { [Category("Movement/Pathfinding")] [Description("Makes the agent wander randomly within the navigation map")] public class Wander : ActionTask { [Tooltip("The speed to wander with.")] public BBParameter speed = 4; [Tooltip("The distance to keep from each wander point.")] public BBParameter keepDistance = 0.1f; [Tooltip("A wander point can't be closer than this distance")] public BBParameter minWanderDistance = 5; [Tooltip("A wander point can't be further than this distance")] public BBParameter maxWanderDistance = 20; [Tooltip("If enabled, will keep wandering forever. If not, only one wander point will be performed.")] public bool repeat = true; [Tooltip("If enabled,will execute a move and exit")] public bool forget; private Vector3? lastPosition; protected override void OnExecute() { agent.speed = speed.value; DoWander(); } protected override void OnUpdate() { if ( !agent.pathPending && agent.remainingDistance <= agent.stoppingDistance + keepDistance.value ) { if ( repeat ) { DoWander(); } else { EndAction(); } lastPosition = null; } else { if (forget) { EndAction(); } } } void DoWander() { if (agent.isOnNavMesh is false) { EndAction(false); return; } var min = minWanderDistance.value; var max = maxWanderDistance.value; min = Mathf.Clamp(min, 0.01f, max); max = Mathf.Clamp(max, min, max); var wanderPos = agent.transform.position; if (lastPosition.HasValue) { wanderPos = lastPosition.Value; } else { while ((wanderPos - agent.transform.position).magnitude < min) { wanderPos = (Random.insideUnitSphere * max) + agent.transform.position; } } NavMeshHit hit; if ( NavMesh.SamplePosition(wanderPos, out hit, agent.height * 2, NavMesh.AllAreas) ) { try { agent.SetDestination(hit.position); lastPosition = hit.position; } catch (Exception e) { Debug.LogWarning(agent.gameObject.name); Debug.LogException(e); } } } protected override void OnPause() { OnStop(); } protected override void OnStop() { if (agent.gameObject.activeSelf && agent.isOnNavMesh) { if (forget is false) agent.ResetPath(); } } protected override void OnStop(bool interrupted) { base.OnStop(interrupted); if (interrupted) { lastPosition = null; } } } }