/// <summary> /// Force to apply to the vehicle /// </summary> /// <returns> /// A <see cref="Vector3"/> /// </returns> protected override Vector3 CalculateForce() { Vector3 forceNode = Vector3.zero; if (_path != null) { var tStruct = new PathRelativePosition(); var futurePosition = Vehicle.PredictFuturePosition(_predictionTime); var futurePathPoint = _path.MapPointToPath(futurePosition, ref tStruct); #if TRACE_PATH Debug.DrawLine(Vehicle.Position, futurePosition, Color.red); Debug.DrawLine(Vehicle.Position, futurePathPoint, Color.green); #endif forceNode = Vehicle.GetSeekVector(futurePathPoint, false); } return(forceNode); }
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); Vector3 offset = _menace.Position - position; float distance = offset.magnitude; float roughTime = distance / _menace.Speed; float predictionTime = ((roughTime > _predictionTime) ? _predictionTime : roughTime); Vector3 target = _menace.PredictFuturePosition(predictionTime); // This was the totality of SteerToFlee Vector3 desiredVelocity = position - target; 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. */ Vector3 futurePosition = Vehicle.PredictFuturePosition(_minTimeToCollision); Vector3 movement = futurePosition - Vehicle.Position; #if ANNOTATE_NAVMESH Debug.DrawRay(Vehicle.Position, movement, Color.cyan); #endif if (_offMeshCheckingEnabled) { Vector3 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); } else // 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); } Vector3 avoidance = Vector3.zero; Profiler.BeginSample("Calculate NavMesh avoidance"); Vector3 moveDirection = Vehicle.Velocity.normalized; 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); }