protected override Vector3 CalculateForce() { if (_menace == null || (Vehicle.Position - _menace.Position).sqrMagnitude > _sqrSafetyDistance) { return(Vector3.zero); } // offset from this to menace, that distance, unit vector toward menace var position = Vehicle.PredictFutureDesiredPosition(_predictionTime); var offset = _menace.Position - position; var distance = offset.magnitude; var roughTime = distance / _menace.Speed; var predictionTime = ((roughTime > _predictionTime) ? _predictionTime : roughTime); //var target = _menace.PredictFuturePosition(predictionTime); var target = _menace.PredictFuturePosition(predictionTime) + _offset; // This was the totality of SteerToFlee var desiredVelocity = position - target; //Debug.DrawRay(Vehicle.Position, desiredVelocity, Color.blue); return(desiredVelocity - Vehicle.DesiredVelocity); }
/// <summary> /// Calculates the force necessary to stay on the navmesh /// </summary> /// <returns> /// Force necessary to stay on the navmesh, or Vector3.zero /// </returns> /// <remarks> /// If the Vehicle is too far off the navmesh, Vector3.zero is retured. /// This won't lead back to the navmesh, but there's no way to determine /// a way back onto it. /// </remarks> protected override Vector3 CalculateForce() { NavMeshHit hit; /* * While we could just calculate line as (Velocity * predictionTime) * and save ourselves the substraction, this allows other vehicles to * override PredictFuturePosition for their own ends. */ var futurePosition = Vehicle.PredictFuturePosition(_minTimeToCollision); var movement = futurePosition - Vehicle.Position; #if ANNOTATE_NAVMESH Debug.DrawRay(Vehicle.Position, movement, Color.cyan); #endif if (_offMeshCheckingEnabled) { var probePosition = Vehicle.Position + _probePositionOffset; Profiler.BeginSample("Off-mesh checking"); NavMesh.SamplePosition(probePosition, out hit, _probeRadius, _navMeshLayerMask); Profiler.EndSample(); if (!hit.hit) { // we're not on the navmesh Profiler.BeginSample("Find closest edge"); NavMesh.FindClosestEdge(probePosition, out hit, _navMeshLayerMask); Profiler.EndSample(); if (hit.hit) { // closest edge found #if ANNOTATE_NAVMESH Debug.DrawLine(probePosition, hit.position, Color.red); #endif return((hit.position - probePosition).normalized * Vehicle.MaxForce); } // no closest edge - too far off the mesh #if ANNOTATE_NAVMESH Debug.DrawLine(probePosition, probePosition + Vector3.up * 3, Color.red); #endif return(Vector3.zero); } } Profiler.BeginSample("NavMesh raycast"); NavMesh.Raycast(Vehicle.Position, futurePosition, out hit, _navMeshLayerMask); Profiler.EndSample(); if (!hit.hit) { return(Vector3.zero); } Profiler.BeginSample("Calculate NavMesh avoidance"); var moveDirection = Vehicle.Velocity.normalized; var avoidance = OpenSteerUtility.PerpendicularComponent(hit.normal, moveDirection); avoidance.Normalize(); #if ANNOTATE_NAVMESH Debug.DrawLine(Vehicle.Position, Vehicle.Position + avoidance, Color.white); #endif avoidance += moveDirection * Vehicle.MaxForce * _avoidanceForceFactor; #if ANNOTATE_NAVMESH Debug.DrawLine(Vehicle.Position, Vehicle.Position + avoidance, Color.yellow); #endif Profiler.EndSample(); return(avoidance); }