/// <summary>
    /// Update the steering data based on match velocity behavior.
    /// </summary>
    /// <param name='pCurrentKinematicData'>
    /// Kinematic data.
    /// </param>
    /// <param name='pCurrentsteeringData'>
    /// Steering data.
    /// </param>
    public override void getSteeringData(ref KINEMATIC_DATA pCurrentKinematicData, ref STEERING_DATA pCurrentSteeringData)
    {
        // Target data.
        GameObject lTarget = GameObject.FindWithTag("thePlayer");
        cPlayerController lPlayerController = lTarget.GetComponent<cPlayerController>();
        Transform lTargetTransform = lTarget.GetComponent<Transform>();
        Vector3 lTargetPosition = lTargetTransform.position;

        // Movement adjustment data.
        float lTimeToTarget = 12.25f;

        // Get the direction of the target and set it as target linear acceleration.
        pCurrentSteeringData.mLinear = lPlayerController.mKinematicData.mVelocity - pCurrentKinematicData.mVelocity;
        pCurrentSteeringData.mLinear /= lTimeToTarget;

        // Clip the linear acceleration if necessary.
        if (pCurrentSteeringData.mLinear.magnitude > pCurrentSteeringData.mMaxLinearAcceleration)
        {
            pCurrentSteeringData.mLinear.Normalize();
            pCurrentSteeringData.mLinear *= pCurrentSteeringData.mMaxLinearAcceleration;
        }

        // Stop any possible rotation.
        pCurrentSteeringData.mAngular = Quaternion.identity;
    }
    /// <summary>
    /// Update the steering data based on wander behavior.
    /// </summary>
    /// <param name='pCurrentKinematicData'>
    /// Kinematic data.
    /// </param>
    /// <param name='pCurrentsteeringData'>
    /// Steering data.
    /// </param>
    public override void getSteeringData(ref KINEMATIC_DATA pCurrentKinematicData, ref STEERING_DATA pCurrentSteeringData)
    {
        // Movement adjustment data.
        float lDirectionChangeProbability = 70.0f;
        float angleOfChange = 75.0f;

        // Angle for changing wander orientation
        Quaternion angleQ = Quaternion.identity;

        // If it is time to change wander orientation, get an angle and rotate orientation.
        if (Random.Range(0.0f, 100.0f) < lDirectionChangeProbability)
        {
            float Anglemutator = Random.value - Random.value;
            float angleChangeIndegrees = angleOfChange * Anglemutator;

            angleQ = Quaternion.AngleAxis(angleChangeIndegrees, Vector3.up);
        }

        // Set probe location and new velocity.
        Vector3 probeLocation;
        if (pCurrentKinematicData.mVelocity != Vector3.zero)
            probeLocation = pCurrentKinematicData.mVelocity * 2;
        else
            probeLocation = new Vector3(pCurrentKinematicData.mPosition[0].x+5.0f, 0.0f, pCurrentKinematicData.mPosition[0].z+5.0f);
        Vector3 newVelocity = angleQ* pCurrentKinematicData.mVelocity;
        newVelocity *= 10;
        newVelocity += probeLocation;

        // Update linear acceleration based on new velocity.
        pCurrentSteeringData.mLinear = newVelocity;
        pCurrentSteeringData.mLinear.y = 0.0f;
        pCurrentSteeringData.mLinear.Normalize();
        pCurrentSteeringData.mLinear *= pCurrentSteeringData.mMaxLinearAcceleration;
    }
    /// <summary>
    /// Get new orientation based on current look direction.
    /// </summary>
    /// <returns>
    /// The new orientation.
    /// </returns>
    /// <param name='pCurrentKinematicData'>
    /// Current kinematic data.
    /// </param>
    public static Quaternion getNewOrientation(KINEMATIC_DATA pCurrentKinematicData)
    {
        if (pCurrentKinematicData.mVelocity.magnitude > 0)
        {
            pCurrentKinematicData.mOrientation = Quaternion.LookRotation(pCurrentKinematicData.mVelocity);
        }

        return pCurrentKinematicData.mOrientation;
    }
    /// <summary>
    /// Update the steering data based on arrive behavior.
    /// </summary>
    /// <param name='pCurrentKinematicData'>
    /// Kinematic data.
    /// </param>
    /// <param name='pCurrentsteeringData'>
    /// Steering data.
    /// </param>
    public override void getSteeringData(ref KINEMATIC_DATA pCurrentKinematicData, ref STEERING_DATA pCurrentSteeringData)
    {
        // Target data.
        GameObject lTarget = GameObject.FindWithTag("thePlayer");
        Transform lTargetTransform = lTarget.GetComponent<Transform>();
        Vector3 lTargetPosition = lTargetTransform.position;

        // Movement adjustment data.
        float lTargetRadius = 3.5f;
        float lSlowRadius = 4.5f;
        float lTimeToTarget = 2.25f;
        float lTargetSpeed = pCurrentKinematicData.mMaxVelocity;

        // Get the direction and distance to target.
        Vector3 lDirectionTowardsTarget = lTargetPosition - pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1];
        float lDistanceToTarget = lDirectionTowardsTarget.magnitude;

        // If we are within target radius, stop movement and rotation.
        if (lDistanceToTarget < lTargetRadius)
        {
            pCurrentSteeringData.mLinear = Vector3.zero;
            pCurrentKinematicData.mVelocity = Vector3.zero;
            return;
        }

        // If we are outside slow radius. go full speed ...
        if (lDistanceToTarget > lSlowRadius)
        {
            lTargetSpeed = lDistanceToTarget;
        }
        // Otherwise calculate scaled speed.
        else
        {
            lTargetSpeed = pCurrentKinematicData.mMaxVelocity * lDistanceToTarget/ lSlowRadius;
        }

        // Get the target velocity by combining speed and direction.
        Vector3 lTargetVelocity = lDirectionTowardsTarget;
        lTargetVelocity.Normalize();
        lTargetVelocity *= lTargetSpeed;

        // Adjust linear acceleration accordingly.
        pCurrentSteeringData.mLinear = lTargetVelocity - pCurrentKinematicData.mVelocity;
        pCurrentSteeringData.mLinear /= lTimeToTarget;

        // Clip linear acceleration if it is too fast.
        if (pCurrentSteeringData.mLinear.magnitude > pCurrentSteeringData.mMaxLinearAcceleration)
        {
            pCurrentSteeringData.mLinear.Normalize();
            pCurrentSteeringData.mLinear *= pCurrentSteeringData.mMaxLinearAcceleration;
        }

        // Stop any possible rotation.
        pCurrentSteeringData.mAngular = Quaternion.identity;
    }
    /// <summary>
    /// Update the steering data based on pursue behavior.
    /// </summary>
    /// <param name='pCurrentKinematicData'>
    /// Kinematic data.
    /// </param>
    /// <param name='pCurrentsteeringData'>
    /// Steering data.
    /// </param>
    public override void getSteeringData(ref KINEMATIC_DATA pCurrentKinematicData, ref STEERING_DATA pCurrentSteeringData)
    {
        // Target data.
        GameObject lTarget = GameObject.FindWithTag("thePlayer");
        cPlayerController lPlayerController = lTarget.GetComponent<cPlayerController>();
        Transform lTargetTransform = lTarget.GetComponent<Transform>();
        Vector3 lTargetPosition = lTargetTransform.position;

        // Movement adjustment data.
        float lMaxPrediction = 15.0f;
        float lPrediction;

        // Get the direction to the target and distance.
        Vector3 lDirection = lTargetPosition - pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1];
        float lDistance = lDirection.magnitude;

        // Get current speed.
        float lSpeed = pCurrentKinematicData.mVelocity.magnitude;

        // Determine prediction based on speed.
        if (lSpeed <= lDistance / lMaxPrediction)
        {
            lPrediction = lMaxPrediction;
        }
        else
        {
            lPrediction = lDistance / lSpeed;
        }

        // Get the candidate target position where to move.
        Vector3 lCandidatePlayerPosition = lTargetPosition + lPlayerController.mKinematicData.mVelocity * lPrediction;

        // Own addition to remove unnatural behavior in certain situations:

        // Check the difference in angles between forward directions.
        float lDifference = Vector3.Angle(lTargetTransform.forward, pCurrentSteeringData.mLinear);

        // If the angle is proper, update position.
        if (lDifference > 90 && lDifference < 270)
        {
            lTargetPosition = lCandidatePlayerPosition;
        }

        // Own addition ends.

        // Update linear acceleration based on the calculated position.
        pCurrentSteeringData.mLinear = lTargetPosition - pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1];
        pCurrentSteeringData.mLinear.y = 0.0f;
        pCurrentSteeringData.mLinear.Normalize();
        pCurrentSteeringData.mLinear *= pCurrentSteeringData.mMaxLinearAcceleration;
    }
Exemple #6
0
    /// <summary>
    /// Update the kinematic data based on do nothing behavior.
    /// </summary>
    /// <returns>
    /// The updated kinematic data.
    /// </returns>
    /// <param name='pCurrentKinematicData'>
    /// Initial kinematic data.
    /// </param>
    public override KINEMATIC_DATA getKinematicData(ref KINEMATIC_DATA pCurrentKinematicData)
    {
        // Reset kinematic data.
        pCurrentKinematicData.mVelocity = Vector3.zero;
        pCurrentKinematicData.mOrientation = Quaternion.identity;
        pCurrentKinematicData.mRotation = Quaternion.identity;

        // Update positional and orientational kinematic data.
        if (pCurrentKinematicData.mPosition.Count > pCurrentKinematicData.mArrayListSize)
        {
            pCurrentKinematicData.mPosition.RemoveAt(0);

        }
        pCurrentKinematicData.mPosition.Insert(pCurrentKinematicData.mPosition.Count-1, pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1]);

        return pCurrentKinematicData;
    }
    /// <summary>
    /// Update the kinematic data based on wander behavior.
    /// </summary>
    /// <returns>
    /// The updated kinematic data.
    /// </returns>
    /// <param name='pCurrentKinematicData'>
    /// Initial kinematic data.
    /// </param>
    public override KINEMATIC_DATA getKinematicData(ref KINEMATIC_DATA pCurrentKinematicData)
    {
        // Movement adjustment data.
        float lDirectionChangeProbability = 1.0f;

        // Maximum rotation speed.
        float lMaxRotation = 270.0f;

        if (Random.Range(0.0f, 100.0f) < lDirectionChangeProbability)
        {
            // Degrees the NPC will rotate during wander.
            float degrees = (Random.value - Random.value) * lMaxRotation;

            // Calculate end rotation for both when there is and is not an original rotation.
            Quaternion endRotation;
            if (pCurrentKinematicData.mRotation == Quaternion.identity)
            {
                endRotation = Quaternion.Euler(new Vector3(0.0f, degrees, 0.0f));
            }
            else
            {
                endRotation = pCurrentKinematicData.mOrientation * Quaternion.Euler(new Vector3(0.0f, degrees, 0.0f));
            }

            // Apply end rotation to the NPC's orientation.
            Quaternion ltq = Quaternion.Slerp(pCurrentKinematicData.mOrientation, endRotation, 1.0f);
            pCurrentKinematicData.mOrientation = ltq;

            // Update the velocity.
            if (pCurrentKinematicData.mVelocity != Vector3.zero)
                pCurrentKinematicData.mVelocity = pCurrentKinematicData.mOrientation * pCurrentKinematicData.mVelocity;
            else
                pCurrentKinematicData.mVelocity = pCurrentKinematicData.mOrientation * Vector3.forward;

            // Fix the orientation to the final velocity
            pCurrentKinematicData.mOrientation = Quaternion.LookRotation(pCurrentKinematicData.mVelocity);
            if (pCurrentKinematicData.mVelocity.magnitude > pCurrentKinematicData.mMaxVelocity)
            {
                pCurrentKinematicData.mVelocity.Normalize();
                pCurrentKinematicData.mVelocity *= pCurrentKinematicData.mMaxVelocity;
            }
        }

        return pCurrentKinematicData;
    }
Exemple #8
0
    /// <summary>
    /// Update the steering data based on do nothing behavior.
    /// </summary>
    /// <param name='pCurrentKinematicData'>
    /// Kinematic data.
    /// </param>
    /// <param name='pCurrentsteeringData'>
    /// Steering data.
    /// </param>
    public override void getSteeringData(ref KINEMATIC_DATA pCurrentKinematicData, ref STEERING_DATA pCurrentSteeringData)
    {
        // Reset kinematic data.
        pCurrentKinematicData.mVelocity = Vector3.zero;
        pCurrentKinematicData.mOrientation = Quaternion.identity;
        pCurrentKinematicData.mRotation = Quaternion.identity;

        // Update positional and orientational kinematic data.
        if (pCurrentKinematicData.mPosition.Count > pCurrentKinematicData.mArrayListSize)
        {
            pCurrentKinematicData.mPosition.RemoveAt(0);

        }
        pCurrentKinematicData.mPosition.Insert(pCurrentKinematicData.mPosition.Count-1, pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1]);

        // Reset steering data.
        pCurrentSteeringData.mLinear = Vector3.zero;
        pCurrentSteeringData.mAngular = Quaternion.identity;
    }
    /// <summary>
    /// Update the kinematic data based on flee behavior.
    /// </summary>
    /// <returns>
    /// The updated kinematic data.
    /// </returns>
    /// <param name='pCurrentKinematicData'>
    /// Initial kinematic data.
    /// </param>
    public override KINEMATIC_DATA getKinematicData(ref KINEMATIC_DATA pCurrentKinematicData)
    {
        // Target data.
        GameObject lTarget = GameObject.FindWithTag("thePlayer");
        Transform lTargetTransform = lTarget.GetComponent<Transform>();
        Vector3 lTargetPosition = lTargetTransform.position;

        // Calculate velocity away from the target.
        pCurrentKinematicData.mVelocity = pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1] - lTargetPosition;
        pCurrentKinematicData.mVelocity.Normalize();
        pCurrentKinematicData.mVelocity *= pCurrentKinematicData.mMaxVelocity;

        // Update orientation.
        pCurrentKinematicData.mOrientation = getNewOrientation(pCurrentKinematicData);

        // Stop all possible orientation.
        pCurrentKinematicData.mRotation = Quaternion.identity;

        return pCurrentKinematicData;
    }
    /// <summary>
    /// Update the kinematic data based on evade behavior.
    /// </summary>
    /// <returns>
    /// The updated kinematic data.
    /// </returns>
    /// <param name='pCurrentKinematicData'>
    /// Initial kinematic data.
    /// </param>
    public override KINEMATIC_DATA getKinematicData(ref KINEMATIC_DATA pCurrentKinematicData)
    {
        // Target data.
        GameObject lTarget = GameObject.FindWithTag("thePlayer");
        cPlayerController lPlayerController = lTarget.GetComponent<cPlayerController>();
        Transform lTargetTransform = lTarget.GetComponent<Transform>();
        Vector3 lTargetPosition = lTargetTransform.position;

        // Movement adjustment data.
        float lMaxPrediction = 2.0f;
        float lPrediction;

        // Get the direction toward the player and distance.
        Vector3 lDirection = pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1] - lTargetPosition;
        float lDistance = lDirection.magnitude;

        // Get current speed.
        float lSpeed = pCurrentKinematicData.mVelocity.magnitude;

        // Determine prediction based on speed.
        if (lSpeed <= lDistance / lMaxPrediction)
        {
            lPrediction = lMaxPrediction;
        }
        else
        {
            lPrediction = lDistance / lSpeed;
            Debug.Log(lPrediction);
        }

        // Update player position based on prediction.
        lTargetPosition += lPlayerController.mKinematicData.mVelocity * lPrediction;

        // Get new velocity.
        pCurrentKinematicData.mVelocity = pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1] - lTargetPosition;
        pCurrentKinematicData.mVelocity.y = 0.0f;
        pCurrentKinematicData.mVelocity.Normalize();
        pCurrentKinematicData.mVelocity *= pCurrentKinematicData.mMaxVelocity;

        return pCurrentKinematicData;
    }
    /// <summary>
    /// Update the kinematic data based on arrive behavior.
    /// </summary>
    /// <returns>
    /// The updated kinematic data.
    /// </returns>
    /// <param name='pCurrentKinematicData'>
    /// Initial kinematic data.
    /// </param>
    public override KINEMATIC_DATA getKinematicData(ref KINEMATIC_DATA pCurrentKinematicData)
    {
        // Target data.
        GameObject lTarget = GameObject.FindWithTag("thePlayer");
        Transform lTargetTransform = lTarget.GetComponent<Transform>();
        Vector3 lTargetPosition = lTargetTransform.position;

        // Movement adjustment data.
        float lTargetRadius = 3.5f;
        float lTimeToTarget = 2.25f;

        // Set current velocity towards the target position.
        pCurrentKinematicData.mVelocity = lTargetPosition - pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1];

        // If we are within target radius, stop movement and rotation.
        if (pCurrentKinematicData.mVelocity.magnitude < lTargetRadius)
        {
            pCurrentKinematicData.mVelocity = Vector3.zero;
            pCurrentKinematicData.mRotation = Quaternion.identity;
        }

        // Set the velocity so that we arrive in desired time.
        pCurrentKinematicData.mVelocity /= lTimeToTarget;

        // Clip velocity if necessary.
        if (pCurrentKinematicData.mVelocity.magnitude > pCurrentKinematicData.mMaxVelocity)
        {
            pCurrentKinematicData.mVelocity.Normalize();
            pCurrentKinematicData.mVelocity *= pCurrentKinematicData.mMaxVelocity;
        }

        // Adjust orientation to face the target.
        pCurrentKinematicData.mOrientation = getNewOrientation(pCurrentKinematicData);

        // Stop any possible rotation.
        pCurrentKinematicData.mRotation = Quaternion.identity;

        return pCurrentKinematicData;
    }
    /// <summary>
    /// Update the steering data based on evade behavior.
    /// </summary>
    /// <param name='pCurrentKinematicData'>
    /// Kinematic data.
    /// </param>
    /// <param name='pCurrentsteeringData'>
    /// Steering data.
    /// </param>
    public override void getSteeringData(ref KINEMATIC_DATA pCurrentKinematicData, ref STEERING_DATA pCurrentSteeringData)
    {
        // Target data.
        GameObject lTarget = GameObject.FindWithTag("thePlayer");
        cPlayerController lPlayerController = lTarget.GetComponent<cPlayerController>();
        Transform lTargetTransform = lTarget.GetComponent<Transform>();
        Vector3 lTargetPosition = lTargetTransform.position;

        // Movement adjustment data.
        float lMaxPrediction = 2.0f;
        float lPrediction;

        // Get the direction away from the target and distance.
        Vector3 lDirection = pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1] - lTargetPosition;
        float lDistance = lDirection.magnitude;

        // Get current speed
        float lSpeed = pCurrentKinematicData.mVelocity.magnitude;

        // Determine prediction based on speed.
        if (lSpeed <= lDistance / lMaxPrediction)
        {
            lPrediction = lMaxPrediction;
        }
        else
        {
            lPrediction = lDistance / lSpeed;
            Debug.Log(lPrediction);
        }

        // Update player position based on prediction.
        lTargetPosition += lPlayerController.mKinematicData.mVelocity * lPrediction;

        // Get new angular acceleration
        pCurrentSteeringData.mLinear = pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1] - lTargetPosition;
        pCurrentSteeringData.mLinear.y = 0.0f;
        pCurrentSteeringData.mLinear.Normalize();
        pCurrentSteeringData.mLinear *= pCurrentSteeringData.mMaxLinearAcceleration;
    }
    /// <summary>
    /// Update the kinematic data based on match velocity behavior.
    /// </summary>
    /// <returns>
    /// The updated kinematic data.
    /// </returns>
    /// <param name='pCurrentKinematicData'>
    /// Initial kinematic data.
    /// </param>
    public override KINEMATIC_DATA getKinematicData(ref KINEMATIC_DATA pCurrentKinematicData)
    {
        // Target data.
        GameObject lTarget = GameObject.FindWithTag("thePlayer");
        cPlayerController lPlayerController = lTarget.GetComponent<cPlayerController>();
        Transform lTargetTransform = lTarget.GetComponent<Transform>();
        Vector3 lTargetPosition = lTargetTransform.position;

        // Get the direction player is going and set it as target velocity.
        pCurrentKinematicData.mVelocity = lPlayerController.mKinematicData.mVelocity - pCurrentKinematicData.mVelocity;

        // Clip the velocity if necessary.
        if (pCurrentKinematicData.mVelocity.magnitude > pCurrentKinematicData.mMaxVelocity)
        {
            pCurrentKinematicData.mVelocity.Normalize();
            pCurrentKinematicData.mVelocity *= pCurrentKinematicData.mMaxVelocity;
        }

        // Stop any possible rotation.
        pCurrentKinematicData.mRotation = Quaternion.identity;

        return pCurrentKinematicData;
    }
 /// <summary>
 /// Update the steering data.
 /// </summary>
 /// <returns>
 /// The updated steering data.
 /// </returns>
 /// <param name='pCurrentKinematicData'>
 /// Initial kinematic data.
 /// </param>
 /// <param name='pCurrentSteeringData'>
 /// Initial steering data.
 /// </param>
 public abstract void getSteeringData(ref KINEMATIC_DATA pCurrentKinematicData, ref STEERING_DATA pCurrentSteeringData);
 /// <summary>
 /// Update the kinematic data.
 /// </summary>
 /// <returns>
 /// The updated kinematic data.
 /// </returns>
 /// <param name='pCurrentKinematicData'>
 /// Initial kinematic data.
 /// </param>
 public abstract KINEMATIC_DATA getKinematicData(ref KINEMATIC_DATA pCurrentSteeringData);
Exemple #16
0
    /// <summary>
    /// Determines new orientation of the player based on player's velocity (= heading).
    /// </summary>
    /// <returns>
    /// The new orientation.
    /// </returns>
    /// <param name='pCurrentKinematicData'>
    /// Current kinematic data for the player.
    /// </param>
    private Quaternion getNewOrientation(KINEMATIC_DATA pCurrentKinematicData)
    {
        Quaternion rotation = Quaternion.LookRotation(pCurrentKinematicData.mVelocity);
        pCurrentKinematicData.mOrientation = rotation;

        return pCurrentKinematicData.mOrientation;
    }
    /// <summary>
    /// Update the steering data based on align behavior.
    /// </summary>
    /// <param name='pCurrentKinematicData'>
    /// Kinematic data.
    /// </param>
    /// <param name='pCurrentsteeringData'>
    /// Steering data.
    /// </param>
    public override void getSteeringData(ref KINEMATIC_DATA pCurrentKinematicData, ref STEERING_DATA pCurrentSteeringData)
    {
        // Target data.
        GameObject lTarget = GameObject.FindWithTag("thePlayer");
        Transform lTargetTransform = lTarget.GetComponent<Transform>();
        Quaternion lTargetOrientation = lTargetTransform.rotation;

        // Movement adjustment data.
        float lTargetRadius = 13.5f;
        float lSlowRadius = 84.5f;
        float lTimeToTarget = 2.25f;
        float lTargetRotation;

        // Get the magnitude of the needed rotation angle to align.
        Quaternion lNeededRotation = Quaternion.Inverse(lTargetOrientation) * pCurrentKinematicData.mOrientation;
        float lNeededRotationAngle = lNeededRotation.eulerAngles.y;

        // Check whether to rotate clockwise or counterclockwise and adjust the angle.
        if (lNeededRotation.eulerAngles.y >= 180.0f)
        {
            //lNeededRotation = Quaternion.Inverse(pCurrentKinematicData.mOrientation) * lTargetOrientation;
            lNeededRotationAngle = lNeededRotation.eulerAngles.y;
        }
        else if(lNeededRotation.eulerAngles.y < 180.0f)
        {
            lNeededRotationAngle = 0.0f - lNeededRotation.eulerAngles.y;
        }

        // Get additional rotation angle data.
        float lNeededRotationSize = Mathf.Abs(lNeededRotationAngle);
        float lOriginalRotationAngle = pCurrentKinematicData.mRotation.eulerAngles.y;

        // If we are within target radius, stop rotation and return.
        if (lNeededRotationSize < lTargetRadius)
        {
            pCurrentSteeringData.mAngular = Quaternion.identity;
            pCurrentKinematicData.mRotation = Quaternion.identity;
            return;
        }

        // If we are outside slow radius, do maximum rotation.
        if (lNeededRotationSize > lSlowRadius)
        {
            lTargetRotation = pCurrentKinematicData.mMaxRotation;
        }
        // Otherwise gradually slow rotation down.
        else
        {
            lTargetRotation = pCurrentKinematicData.mMaxRotation * lNeededRotationSize / lSlowRadius;
        }

        // Get the final target rotation by combining speed (already in the variable) with direction.
        lTargetRotation *= lNeededRotationAngle / lNeededRotationSize;

        // Get the angle for the target rotation.
        float lTargetRotationAngleY = lTargetRotation - lOriginalRotationAngle;
        lTargetRotationAngleY /= lTimeToTarget;

        // Chekc if the angular acceleration is too fast and clip if needed.
        float lAngularAcceleration = Mathf.Abs(lTargetRotationAngleY);
        if (lAngularAcceleration > pCurrentSteeringData.mMaxAngularAcceleration)
        {
            lTargetRotationAngleY /= lAngularAcceleration;
            lTargetRotationAngleY *= pCurrentSteeringData.mMaxAngularAcceleration;
        }

        // Do not alter x and z angles
        float lRotateX = pCurrentSteeringData.mAngular.eulerAngles.x;
        float lRotateZ = pCurrentSteeringData.mAngular.eulerAngles.z;

        // Get the updated angular acceleration based on the calculated x, y, and z angles.
        pCurrentSteeringData.mAngular = Quaternion.Euler(lRotateX, lTargetRotationAngleY, lRotateZ);

        // Just align orientation, stop all possible movement.
        pCurrentKinematicData.mVelocity = Vector3.zero;
        pCurrentSteeringData.mLinear = Vector3.zero;
    }
    /// <summary>
    /// Update the steering data based on face behavior.
    /// </summary>
    /// <param name='pCurrentKinematicData'>
    /// Kinematic data.
    /// </param>
    /// <param name='pCurrentsteeringData'>
    /// Steering data.
    /// </param>
    public override void getSteeringData(ref KINEMATIC_DATA pCurrentKinematicData, ref STEERING_DATA pCurrentSteeringData)
    {
        // Target data.
        GameObject lTarget = GameObject.FindWithTag("thePlayer");
        Transform lTargetTransform = lTarget.GetComponent<Transform>();
        Vector3 lTargetPosition = lTargetTransform.position;
        Quaternion lOrientationTowardsTarget = lTargetTransform.rotation;

        // Movement adjustment data.
        float lTargetRadius = 13.5f;
        float lSlowRadius = 84.5f;
        float lTimeToTarget = 11.25f;
        float lTargetRotation;

        // Get the direction towards the target.
        Vector3 lDirection = lTargetPosition - pCurrentKinematicData.mPosition[pCurrentKinematicData.mPosition.Count-1];
        if (lDirection.magnitude == 0.0f)
        {
            return;
        }

        // Get the orientation towards target.
        lOrientationTowardsTarget = Quaternion.LookRotation(lDirection);

        // Get the rotation needed to face the player.
        Quaternion lNeededRotation = Quaternion.Inverse(lOrientationTowardsTarget) * pCurrentKinematicData.mOrientation;
        float lNeededRotationAngle = lNeededRotation.eulerAngles.y;

        // Check whether to rotate clockwise or counterclockwise.
        if (lNeededRotation.eulerAngles.y >= 180.0f)
        {
            lNeededRotation = Quaternion.Inverse(pCurrentKinematicData.mOrientation) * lOrientationTowardsTarget;
            lNeededRotationAngle = lNeededRotation.eulerAngles.y;
        }
        else if(lNeededRotation.eulerAngles.y < 180.0f)
        {
            lNeededRotationAngle = 0.0f - lNeededRotation.eulerAngles.y;
        }

        // Get additional rotation angle data.
        float lUnsignedNeededRotationAngle = Mathf.Abs(lNeededRotationAngle);
        float lOriginalRotationAngle = pCurrentKinematicData.mRotation.eulerAngles.y;

        // If we are within target radius, stop rotation and return.
        if (lUnsignedNeededRotationAngle < lTargetRadius)
        {
            pCurrentSteeringData.mAngular = Quaternion.identity;
            pCurrentKinematicData.mRotation = Quaternion.identity;
            return;
        }

        // If we are outside slow radius, do maximum rotation.
        if (lUnsignedNeededRotationAngle > lSlowRadius)
        {
            lTargetRotation = pCurrentKinematicData.mMaxRotation;
        }
        // Otherwise gradually slow rotation.
        else
        {
            lTargetRotation = pCurrentKinematicData.mMaxRotation * lUnsignedNeededRotationAngle / lSlowRadius;
        }

        // Get the final target rotation by combining speed (already in the variable) with direction.
        lTargetRotation *= lNeededRotationAngle / lUnsignedNeededRotationAngle;

        // Get the angle for target rotation.
        float lTargetRotationAngleY = lTargetRotation - lOriginalRotationAngle;
        lTargetRotationAngleY /= lTimeToTarget;

        // Get the absolute target angular acceleration?
        float lAbsAngularAcceleration = Mathf.Abs(lTargetRotationAngleY);
        if (lAbsAngularAcceleration > pCurrentSteeringData.mMaxAngularAcceleration)
        {
            lTargetRotationAngleY /= lAbsAngularAcceleration;
            lTargetRotationAngleY *= pCurrentSteeringData.mMaxAngularAcceleration;
        }

        // Do not alter x and z angles.
        float lRotateX = pCurrentSteeringData.mAngular.eulerAngles.x;
        float lRotateZ = pCurrentSteeringData.mAngular.eulerAngles.z;

        // Get the updated angular acceleration based on the calculated x, y, and z angles.
        pCurrentSteeringData.mAngular = Quaternion.Euler(lRotateX, lTargetRotationAngleY, lRotateZ);

        // Just align orientation, stop all possible movement.
        pCurrentKinematicData.mVelocity = Vector3.zero;
        pCurrentSteeringData.mLinear = Vector3.zero;
    }