/// <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; }
/// <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; }
/// <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);
/// <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; }