/// --------------------------------------------- /// Movement Pack for Behavior Designer Pro /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.BehaviorDesigner.AddOns.MovementPack.Runtime.Tasks { using Opsive.BehaviorDesigner.Runtime.Tasks; using Opsive.GraphDesigner.Runtime; using Opsive.GraphDesigner.Runtime.Variables; using UnityEngine; [Opsive.Shared.Utility.Description("Pursues the specified target. Pursue will predict where the target is headed based on the Target Distance Prediction value.")] [NodeIcon("079b135d5d495e14abd9ad2cb0dfaf9e", "c0515b66e6314734ba5a8f2ec7d6f451")] public class Pursue : MovementBase { [Tooltip("The GameObject that the agent is seeking.")] [SerializeField] protected SharedVariable m_Target; [Tooltip("Specifies how far to predict the distance ahead of the target. Lower values indicate that less distance should be predicated.")] [SerializeField] protected SharedVariable m_DistancePrediction = 20; [Tooltip("Specifies the multiplier for predicting the look ahead distance.")] [SerializeField] protected SharedVariable m_DistancePredictionMultiplier = 20; private Vector3 m_TargetPosition; /// /// The task has started. /// public override void OnStart() { base.OnStart(); if (m_Target == null) { Debug.LogError("Error: A target must be set on the Pursue ability."); return; } m_TargetPosition = m_Target.Value.transform.position; SetDestination(GetTargetDestination()); } /// /// Returns the target destination. /// /// The target destination. private Vector3 GetTargetDestination() { // Calculate the current distance to the target and the current speed. var distance = (m_Target.Value.transform.position - transform.position).magnitude; var velocityMagnitude = m_Pathfinder.Velocity.magnitude; var futurePrediction = 0f; // Set the future prediction to the max prediction if the speed is too small to give an accurate prediction. if (velocityMagnitude <= distance / m_DistancePrediction.Value) { futurePrediction = m_DistancePrediction.Value; } else { futurePrediction = (distance / velocityMagnitude) * m_DistancePredictionMultiplier.Value; } // Predict the future by taking the velocity of the target and multiply it by the future prediction. var lastTargetPosition = m_TargetPosition; m_TargetPosition = m_Target.Value.transform.position; return m_TargetPosition + (m_TargetPosition - lastTargetPosition) * futurePrediction; } /// /// Updates the destination. /// /// Success when the agent arrives. public override TaskStatus OnUpdate() { if (m_Target.Value == null) { return TaskStatus.Failure; } if (HasArrived()) { return TaskStatus.Success; } SetDestination(GetTargetDestination()); return TaskStatus.Running; } /// /// Resets the task values back to their default. /// public override void Reset() { base.Reset(); m_Target = null; m_DistancePrediction = 20; m_DistancePredictionMultiplier = 20; } } }