/// <summary> /// Seeks from the specified position to a destination. /// </summary> /// <param name="position">The position from which to seek.</param> /// <param name="destination">The destination.</param> /// <param name="input">The input.</param> /// <param name="maxAcceleration">The maximum allowed acceleration.</param> /// <returns>The seek acceleration vector</returns> protected Vector3 Seek(Vector3 position, Vector3 destination, SteeringInput input, float maxAcceleration) { var dir = position.DirToXZ(destination); var desiredVelocity = dir.normalized * input.desiredSpeed; return Vector3.ClampMagnitude((desiredVelocity - input.currentPlanarVelocity) / input.deltaTime, maxAcceleration); }
/// <summary> /// Gets an avoidance vector. /// </summary> /// <param name="selfPos">This unit's position.</param> /// <param name="currentVelocity">This unit's current velocity.</param> /// <param name="normalVelocity">This unit's normalized current velocity.</param> /// <param name="unitData">This unit's UnitFacade.</param> /// <param name="otherPos">The other unit's position.</param> /// <param name="otherVelocity">The other unit's velocity.</param> /// <param name="otherData">The other unit's UnitFacade.</param> /// <param name="combinedRadius">The combined radius.</param> /// <returns>An avoidance vector from the other unit's collision position to this unit's collision position - if a collision actually is detected.</returns> private Vector3 GetAvoidVector(Vector3 selfPos, Vector3 currentVelocity, Vector3 normalVelocity, IUnitFacade unitData, Vector3 otherPos, Vector3 otherVelocity, IUnitFacade otherData, float combinedRadius) { Vector3 avoidDirection = GetAvoidDirectionVector(selfPos, currentVelocity, otherPos, otherVelocity, combinedRadius); float avoidMagnitude = avoidDirection.magnitude; if (avoidMagnitude == 0f) { // if there is absolutely no magnitude to the found avoid direction, then ignore it return Vector3.zero; } float vectorLength = combinedRadius * 0.5f; if (vectorLength <= 0f) { // if the units' combined radius is 0, then we cannot avoid return Vector3.zero; } // normalize the avoid vector and then set it's magnitude to the desired vector length (half of the combined radius) Vector3 avoidNormalized = (avoidDirection / avoidMagnitude); Vector3 avoidVector = avoidNormalized * vectorLength; float dotAngle = Vector3.Dot(avoidNormalized, normalVelocity); if (dotAngle <= _cosAvoidAngle) { // the collision is considered "head-on", thus we compute a perpendicular avoid vector instead avoidVector = new Vector3(avoidVector.z, avoidVector.y, -avoidVector.x); } else if (preventPassingInFront && (otherData.determination > unitData.determination) && (Vector3.Dot(otherVelocity, avoidVector) > 0f && Vector3.Dot(currentVelocity, otherVelocity) >= 0f)) { // if supposed to be preventing front-passing, then check whether we should prevent it in this case and if so compute a different avoid vector avoidVector = _selfCollisionPos.DirToXZ(selfPos); } // scale the avoid vector depending on the distance to collision, shorter distances need larger magnitudes and vice versa float collisionDistance = Mathf.Max(1f, selfPos.DirToXZ(_selfCollisionPos).magnitude); avoidVector *= currentVelocity.magnitude / collisionDistance; return avoidVector; }
protected Vector3 Seek(Vector3 position, Vector3 destination, SteeringInput input, float acceleration) { var dir = position.DirToXZ(destination); var desiredVelocity = dir.normalized * acceleration; return desiredVelocity - input.currentPlanarVelocity; }