void TraverseFunnel(RichFunnel fn, float deltaTime, out Vector3 nextPosition, out Quaternion nextRotation) { // Clamp the current position to the navmesh // and update the list of upcoming corners in the path // and store that in the 'nextCorners' field var position3D = UpdateTarget(fn); float elevation; Vector2 position = movementPlane.ToPlane(position3D, out elevation); // Only find nearby walls every 5th frame to improve performance if (Time.frameCount % 5 == 0 && wallForce > 0 && wallDist > 0) { wallBuffer.Clear(); fn.FindWalls(wallBuffer, wallDist); } // Target point steeringTarget = nextCorners[0]; Vector2 targetPoint = movementPlane.ToPlane(steeringTarget); // Direction to target Vector2 dir = targetPoint - position; // Normalized direction to the target Vector2 normdir = VectorMath.Normalize(dir, out distanceToSteeringTarget); // Calculate force from walls Vector2 wallForceVector = CalculateWallForce(position, elevation, normdir); Vector2 targetVelocity; if (approachingPartEndpoint) { targetVelocity = slowdownTime > 0 ? Vector2.zero : normdir * maxSpeed; // Reduce the wall avoidance force as we get closer to our target wallForceVector *= System.Math.Min(distanceToSteeringTarget / 0.5f, 1); if (distanceToSteeringTarget <= endReachedDistance) { // Reached the end of the path or an off mesh link NextPart(); } } else { var nextNextCorner = nextCorners.Count > 1 ? movementPlane.ToPlane(nextCorners[1]) : position + 2 * dir; targetVelocity = (nextNextCorner - targetPoint).normalized * maxSpeed; } var forwards = movementPlane.ToPlane(simulatedRotation * (orientation == OrientationMode.YAxisForward ? Vector3.up : Vector3.forward)); Vector2 accel = MovementUtilities.CalculateAccelerationToReachPoint(targetPoint - position, targetVelocity, velocity2D, acceleration, rotationSpeed, maxSpeed, forwards); // Update the velocity using the acceleration velocity2D += (accel + wallForceVector * wallForce) * deltaTime; // Distance to the end of the path (almost as the crow flies) var distanceToEndOfPath = distanceToSteeringTarget + Vector3.Distance(steeringTarget, fn.exactEnd); var slowdownFactor = distanceToEndOfPath < maxSpeed *slowdownTime?Mathf.Sqrt(distanceToEndOfPath / (maxSpeed *slowdownTime)) : 1; FinalMovement(position3D, deltaTime, distanceToEndOfPath, slowdownFactor, out nextPosition, out nextRotation); }
private void TraverseFunnel(RichFunnel fn, float deltaTime) { float elevation; Vector2 vector = this.movementPlane.ToPlane(this.UpdateTarget(fn), out elevation); if (Time.frameCount % 5 == 0 && this.wallForce > 0f && this.wallDist > 0f) { this.wallBuffer.Clear(); fn.FindWalls(this.wallBuffer, this.wallDist); } Vector2 vector2 = this.waypoint = this.movementPlane.ToPlane(this.nextCorners[0]); Vector2 vector3 = vector2 - vector; object obj = this.lastCorner && this.nextCorners.Count == 1; Vector2 vector4 = VectorMath.Normalize(vector3, out this.distanceToWaypoint); Vector2 a = this.CalculateWallForce(vector, elevation, vector4); object obj2 = obj; Vector2 targetVelocity; if (obj2 != null) { targetVelocity = ((this.slowdownTime > 0f) ? Vector2.zero : (vector4 * this.maxSpeed)); a *= Math.Min(this.distanceToWaypoint / 0.5f, 1f); if (this.distanceToWaypoint <= this.endReachedDistance) { this.NextPart(); } } else { targetVelocity = (((this.nextCorners.Count > 1) ? this.movementPlane.ToPlane(this.nextCorners[1]) : (vector + 2f * vector3)) - vector2).normalized * this.maxSpeed; } Vector2 a2 = MovementUtilities.CalculateAccelerationToReachPoint(vector2 - vector, targetVelocity, this.velocity2D, this.acceleration, this.maxSpeed); this.velocity2D += (a2 + a * this.wallForce) * deltaTime; float distanceToEndOfPath = fn.DistanceToEndOfPath; float num = (this.slowdownTime > 0f) ? (distanceToEndOfPath / (this.maxSpeed * this.slowdownTime)) : 1f; this.velocity2D = MovementUtilities.ClampVelocity(this.velocity2D, this.maxSpeed, num, this.slowWhenNotFacingTarget, this.movementPlane.ToPlane(this.rotationIn2D ? this.tr.up : this.tr.forward)); base.ApplyGravity(deltaTime); if (this.rvoController != null && this.rvoController.enabled) { Vector3 pos = this.movementPlane.ToWorld(vector + Vector2.ClampMagnitude(this.velocity2D, distanceToEndOfPath), elevation); this.rvoController.SetTarget(pos, this.velocity2D.magnitude, this.maxSpeed); } Vector2 vector5 = base.CalculateDeltaToMoveThisFrame(vector, distanceToEndOfPath, deltaTime); float num2 = (obj2 != null) ? Mathf.Clamp01(1.1f * num - 0.1f) : 1f; this.RotateTowards(vector5, this.rotationSpeed * num2 * deltaTime); base.Move(this.movementPlane.ToWorld(vector, elevation), this.movementPlane.ToWorld(vector5, this.verticalVelocity * deltaTime)); }
// Token: 0x0600217C RID: 8572 RVA: 0x0018E4A4 File Offset: 0x0018C6A4 private void TraverseFunnel(RichFunnel fn, float deltaTime, out Vector3 nextPosition, out Quaternion nextRotation) { Vector3 vector = this.UpdateTarget(fn); float elevation; Vector2 vector2 = this.movementPlane.ToPlane(vector, out elevation); if (Time.frameCount % 5 == 0 && this.wallForce > 0f && this.wallDist > 0f) { this.wallBuffer.Clear(); fn.FindWalls(this.wallBuffer, this.wallDist); } this.steeringTarget = this.nextCorners[0]; Vector2 vector3 = this.movementPlane.ToPlane(this.steeringTarget); Vector2 vector4 = vector3 - vector2; Vector2 vector5 = VectorMath.Normalize(vector4, out this.distanceToSteeringTarget); Vector2 a = this.CalculateWallForce(vector2, elevation, vector5); Vector2 targetVelocity; if (this.approachingPartEndpoint) { targetVelocity = ((this.slowdownTime > 0f) ? Vector2.zero : (vector5 * this.maxSpeed)); a *= Math.Min(this.distanceToSteeringTarget / 0.5f, 1f); if (this.distanceToSteeringTarget <= this.endReachedDistance) { this.NextPart(); } } else { targetVelocity = (((this.nextCorners.Count > 1) ? this.movementPlane.ToPlane(this.nextCorners[1]) : (vector2 + 2f * vector4)) - vector3).normalized * this.maxSpeed; } Vector2 forwardsVector = this.movementPlane.ToPlane(this.simulatedRotation * (this.rotationIn2D ? Vector3.up : Vector3.forward)); Vector2 a2 = MovementUtilities.CalculateAccelerationToReachPoint(vector3 - vector2, targetVelocity, this.velocity2D, this.acceleration, this.rotationSpeed, this.maxSpeed, forwardsVector); this.velocity2D += (a2 + a * this.wallForce) * deltaTime; float num = this.distanceToSteeringTarget + Vector3.Distance(this.steeringTarget, fn.exactEnd); float slowdownFactor = (num < this.maxSpeed * this.slowdownTime) ? Mathf.Sqrt(num / (this.maxSpeed * this.slowdownTime)) : 1f; this.FinalMovement(vector, deltaTime, num, slowdownFactor, out nextPosition, out nextRotation); }
protected virtual void Update() { RichAI.deltaTime = Mathf.Min(Time.smoothDeltaTime * 2f, Time.deltaTime); if (this.rp != null) { RichPathPart currentPart = this.rp.GetCurrentPart(); RichFunnel richFunnel = currentPart as RichFunnel; if (richFunnel != null) { Vector3 vector = this.UpdateTarget(richFunnel); if (Time.frameCount % 5 == 0) { this.wallBuffer.Clear(); richFunnel.FindWalls(this.wallBuffer, this.wallDist); } int num = 0; Vector3 vector2 = this.buffer[num]; Vector3 vector3 = vector2 - vector; vector3.y = 0f; bool flag = Vector3.Dot(vector3, this.currentTargetDirection) < 0f; if (flag && this.buffer.Count - num > 1) { num++; vector2 = this.buffer[num]; } if (vector2 != this.lastTargetPoint) { this.currentTargetDirection = vector2 - vector; this.currentTargetDirection.y = 0f; this.currentTargetDirection.Normalize(); this.lastTargetPoint = vector2; } vector3 = vector2 - vector; vector3.y = 0f; float magnitude = vector3.magnitude; this.distanceToWaypoint = magnitude; vector3 = ((magnitude != 0f) ? (vector3 / magnitude) : Vector3.zero); Vector3 vector4 = vector3; Vector3 vector5 = Vector3.zero; if (this.wallForce > 0f && this.wallDist > 0f) { float num2 = 0f; float num3 = 0f; for (int i = 0; i < this.wallBuffer.Count; i += 2) { Vector3 vector6 = AstarMath.NearestPointStrict(this.wallBuffer[i], this.wallBuffer[i + 1], this.tr.position); float sqrMagnitude = (vector6 - vector).sqrMagnitude; if (sqrMagnitude <= this.wallDist * this.wallDist) { Vector3 normalized = (this.wallBuffer[i + 1] - this.wallBuffer[i]).normalized; float num4 = Vector3.Dot(vector3, normalized) * (1f - Math.Max(0f, 2f * (sqrMagnitude / (this.wallDist * this.wallDist)) - 1f)); if (num4 > 0f) { num3 = Math.Max(num3, num4); } else { num2 = Math.Max(num2, -num4); } } } Vector3 vector7 = Vector3.Cross(Vector3.up, vector3); vector5 = vector7 * (num3 - num2); } bool flag2 = this.lastCorner && this.buffer.Count - num == 1; if (flag2) { if (this.slowdownTime < 0.001f) { this.slowdownTime = 0.001f; } Vector3 vector8 = vector2 - vector; vector8.y = 0f; if (this.preciseSlowdown) { vector3 = (6f * vector8 - 4f * this.slowdownTime * this.velocity) / (this.slowdownTime * this.slowdownTime); } else { vector3 = 2f * (vector8 - this.slowdownTime * this.velocity) / (this.slowdownTime * this.slowdownTime); } vector3 = Vector3.ClampMagnitude(vector3, this.acceleration); vector5 *= Math.Min(magnitude / 0.5f, 1f); if (magnitude < this.endReachedDistance) { this.NextPart(); } } else { vector3 *= this.acceleration; } this.velocity += (vector3 + vector5 * this.wallForce) * RichAI.deltaTime; if (this.slowWhenNotFacingTarget) { float num5 = (Vector3.Dot(vector4, this.tr.forward) + 0.5f) * 0.6666667f; float num6 = Mathf.Sqrt(this.velocity.x * this.velocity.x + this.velocity.z * this.velocity.z); float y = this.velocity.y; this.velocity.y = 0f; float num7 = Mathf.Min(num6, this.maxSpeed * Mathf.Max(num5, 0.2f)); this.velocity = Vector3.Lerp(this.tr.forward * num7, this.velocity.normalized * num7, Mathf.Clamp((!flag2) ? 0f : (magnitude * 2f), 0.5f, 1f)); this.velocity.y = y; } else { float num8 = Mathf.Sqrt(this.velocity.x * this.velocity.x + this.velocity.z * this.velocity.z); num8 = this.maxSpeed / num8; if (num8 < 1f) { this.velocity.x = this.velocity.x * num8; this.velocity.z = this.velocity.z * num8; } } if (flag2) { Vector3 trotdir = Vector3.Lerp(this.velocity, this.currentTargetDirection, Math.Max(1f - magnitude * 2f, 0f)); this.RotateTowards(trotdir); } else { this.RotateTowards(this.velocity); } this.velocity += RichAI.deltaTime * this.gravity; if (this.rvoController != null && this.rvoController.enabled) { this.tr.position = vector; this.rvoController.Move(this.velocity); } else if (this.controller != null && this.controller.enabled) { this.tr.position = vector; this.controller.Move(this.velocity * RichAI.deltaTime); } else { float y2 = vector.y; vector += this.velocity * RichAI.deltaTime; vector = this.RaycastPosition(vector, y2); this.tr.position = vector; } } else if (this.rvoController != null && this.rvoController.enabled) { this.rvoController.Move(Vector3.zero); } if (currentPart is RichSpecial) { RichSpecial rs = currentPart as RichSpecial; if (!this.traversingSpecialPath) { base.StartCoroutine(this.TraverseSpecial(rs)); } } } else if (this.rvoController != null && this.rvoController.enabled) { this.rvoController.Move(Vector3.zero); } else if (!(this.controller != null) || !this.controller.enabled) { this.tr.position = this.RaycastPosition(this.tr.position, this.tr.position.y); } }
/** Update is called once per frame */ protected virtual void Update() { deltaTime = Mathf.Min(Time.smoothDeltaTime * 2, Time.deltaTime); if (rp != null) { //System.Diagnostics.Stopwatch w = new System.Diagnostics.Stopwatch(); //w.Start(); RichPathPart pt = rp.GetCurrentPart(); RichFunnel fn = pt as RichFunnel; if (fn != null) { //Clear buffers for reuse Vector3 position = UpdateTarget(fn); //tr.position = ps; //Only get walls every 5th frame to save on performance if (Time.frameCount % 5 == 0) { wallBuffer.Clear(); fn.FindWalls(wallBuffer, wallDist); } /*for (int i=0;i<wallBuffer.Count;i+=2) { * Debug.DrawLine (wallBuffer[i],wallBuffer[i+1],Color.magenta); * }*/ //Pick next waypoint if current is reached int tgIndex = 0; /*if (buffer.Count > 1) { * if ((buffer[tgIndex]-tr.position).sqrMagnitude < pickNextWaypointDist*pickNextWaypointDist) { * tgIndex++; * } * }*/ //Target point Vector3 tg = buffer[tgIndex]; Vector3 dir = tg - position; dir.y = 0; bool passedTarget = Vector3.Dot(dir, currentTargetDirection) < 0; //Check if passed target in another way if (passedTarget && buffer.Count - tgIndex > 1) { tgIndex++; tg = buffer[tgIndex]; } if (tg != lastTargetPoint) { currentTargetDirection = (tg - position); currentTargetDirection.y = 0; currentTargetDirection.Normalize(); lastTargetPoint = tg; //Debug.DrawRay (tr.position, Vector3.down*2,Color.blue,0.2f); } //Direction to target dir = (tg - position); dir.y = 0; float magn = dir.magnitude; //Write out for other scripts to read distanceToWaypoint = magn; //Normalize dir = magn == 0 ? Vector3.zero : dir / magn; Vector3 normdir = dir; Vector3 force = Vector3.zero; if (wallForce > 0 && wallDist > 0) { float wLeft = 0; float wRight = 0; for (int i = 0; i < wallBuffer.Count; i += 2) { Vector3 closest = AstarMath.NearestPointStrict(wallBuffer[i], wallBuffer[i + 1], tr.position); float dist = (closest - position).sqrMagnitude; if (dist > wallDist * wallDist) { continue; } Vector3 tang = (wallBuffer[i + 1] - wallBuffer[i]).normalized; //Using the fact that all walls are laid out clockwise (seeing from inside) //Then left and right (ish) can be figured out like this float dot = Vector3.Dot(dir, tang) * (1 - System.Math.Max(0, (2 * (dist / (wallDist * wallDist)) - 1))); if (dot > 0) { wRight = System.Math.Max(wRight, dot); } else { wLeft = System.Math.Max(wLeft, -dot); } } Vector3 norm = Vector3.Cross(Vector3.up, dir); force = norm * (wRight - wLeft); //Debug.DrawRay (tr.position, force, Color.cyan); } //Is the endpoint of the path (part) the current target point bool endPointIsTarget = lastCorner && buffer.Count - tgIndex == 1; if (endPointIsTarget) { //Use 2nd or 3rd degree motion equation to figure out acceleration to reach target in "exact" [slowdownTime] seconds //Clamp to avoid divide by zero if (slowdownTime < 0.001f) { slowdownTime = 0.001f; } Vector3 diff = tg - position; diff.y = 0; if (preciseSlowdown) { //{ t = slowdownTime //{ diff = vt + at^2/2 + qt^3/6 //{ 0 = at + qt^2/2 //{ solve for a dir = (6 * diff - 4 * slowdownTime * velocity) / (slowdownTime * slowdownTime); } else { dir = 2 * (diff - slowdownTime * velocity) / (slowdownTime * slowdownTime); } dir = Vector3.ClampMagnitude(dir, acceleration); force *= System.Math.Min(magn / 0.5f, 1); if (magn < endReachedDistance) { //END REACHED NextPart(); } } else { dir *= acceleration; } //Debug.DrawRay (tr.position+Vector3.up, dir*3, Color.blue); velocity += (dir + force * wallForce) * deltaTime; if (slowWhenNotFacingTarget) { float dot = (Vector3.Dot(normdir, tr.forward) + 0.5f) * (1.0f / 1.5f); //velocity = Vector3.ClampMagnitude (velocity, maxSpeed * Mathf.Max (dot, 0.2f) ); float xzmagn = Mathf.Sqrt(velocity.x * velocity.x + velocity.z * velocity.z); float prevy = velocity.y; velocity.y = 0; float mg = Mathf.Min(xzmagn, maxSpeed * Mathf.Max(dot, 0.2f)); velocity = Vector3.Lerp(tr.forward * mg, velocity.normalized * mg, Mathf.Clamp(endPointIsTarget ? (magn * 2) : 0, 0.5f, 1.0f)); velocity.y = prevy; } else { // Clamp magnitude on the XZ axes float xzmagn = Mathf.Sqrt(velocity.x * velocity.x + velocity.z * velocity.z); xzmagn = maxSpeed / xzmagn; if (xzmagn < 1) { velocity.x *= xzmagn; velocity.z *= xzmagn; //Vector3.ClampMagnitude (velocity, maxSpeed); } } //Debug.DrawLine (tr.position, tg, lastCorner ? Color.red : Color.green); if (endPointIsTarget) { Vector3 trotdir = Vector3.Lerp(velocity, currentTargetDirection, System.Math.Max(1 - magn * 2, 0)); RotateTowards(trotdir); } else { RotateTowards(velocity); } //Applied after rotation to enable proper checks on if velocity is zero velocity += deltaTime * gravity; if (rvoController != null && rvoController.enabled) { //Use RVOController tr.position = position; rvoController.Move(velocity); } else if (controller != null && controller.enabled) { //Use CharacterController tr.position = position; controller.Move(velocity * deltaTime); } else { //Use Transform float lasty = position.y; position += velocity * deltaTime; position = RaycastPosition(position, lasty); tr.position = position; } } else { if (rvoController != null && rvoController.enabled) { //Use RVOController rvoController.Move(Vector3.zero); } } if (pt is RichSpecial) { RichSpecial rs = pt as RichSpecial; if (!traversingSpecialPath) { StartCoroutine(TraverseSpecial(rs)); } } //w.Stop(); //Debug.Log ((w.Elapsed.TotalMilliseconds*1000)); } else { if (rvoController != null && rvoController.enabled) { //Use RVOController rvoController.Move(Vector3.zero); } else if (controller != null && controller.enabled) { } else { tr.position = RaycastPosition(tr.position, tr.position.y); } } }
protected virtual void Update() { RichAI.deltaTime = Mathf.Min(Time.smoothDeltaTime * 2f, Time.deltaTime); if (this.rp != null) { RichPathPart currentPart = this.rp.GetCurrentPart(); RichFunnel richFunnel = currentPart as RichFunnel; if (richFunnel != null) { Vector3 vector = this.UpdateTarget(richFunnel); if (Time.frameCount % 5 == 0 && this.wallForce > 0f && this.wallDist > 0f) { this.wallBuffer.Clear(); richFunnel.FindWalls(this.wallBuffer, this.wallDist); } int num = 0; Vector3 vector2 = this.nextCorners[num]; Vector3 vector3 = vector2 - vector; vector3.y = 0f; bool flag = Vector3.Dot(vector3, this.currentTargetDirection) < 0f; if (flag && this.nextCorners.Count - num > 1) { num++; vector2 = this.nextCorners[num]; } if (vector2 != this.lastTargetPoint) { this.currentTargetDirection = vector2 - vector; this.currentTargetDirection.y = 0f; this.currentTargetDirection.Normalize(); this.lastTargetPoint = vector2; } vector3 = vector2 - vector; vector3.y = 0f; Vector3 vector4 = VectorMath.Normalize(vector3, out this.distanceToWaypoint); bool flag2 = this.lastCorner && this.nextCorners.Count - num == 1; if (flag2 && this.distanceToWaypoint < 0.01f * this.maxSpeed) { this.velocity = (vector2 - vector) * 100f; } else { Vector3 a = this.CalculateWallForce(vector, vector4); Vector2 vector5; if (flag2) { vector5 = this.CalculateAccelerationToReachPoint(RichAI.To2D(vector2 - vector), Vector2.zero, RichAI.To2D(this.velocity)); a *= Math.Min(this.distanceToWaypoint / 0.5f, 1f); if (this.distanceToWaypoint < this.endReachedDistance) { this.NextPart(); } } else { Vector3 a2 = (num >= this.nextCorners.Count - 1) ? ((vector2 - vector) * 2f + vector) : this.nextCorners[num + 1]; Vector3 v = (a2 - vector2).normalized * this.maxSpeed; vector5 = this.CalculateAccelerationToReachPoint(RichAI.To2D(vector2 - vector), RichAI.To2D(v), RichAI.To2D(this.velocity)); } this.velocity += (new Vector3(vector5.x, 0f, vector5.y) + a * this.wallForce) * RichAI.deltaTime; } TriangleMeshNode currentNode = richFunnel.CurrentNode; Vector3 b; if (currentNode != null) { b = currentNode.ClosestPointOnNode(vector); } else { b = vector; } float magnitude = (richFunnel.exactEnd - b).magnitude; float num2 = this.maxSpeed; num2 *= Mathf.Sqrt(Mathf.Min(1f, magnitude / (this.maxSpeed * this.slowdownTime))); if (this.slowWhenNotFacingTarget) { float num3 = Mathf.Max((Vector3.Dot(vector4, this.tr.forward) + 0.5f) / 1.5f, 0.2f); num2 *= num3; float num4 = VectorMath.MagnitudeXZ(this.velocity); float y = this.velocity.y; this.velocity.y = 0f; num4 = Mathf.Min(num4, num2); this.velocity = Vector3.Lerp(this.velocity.normalized * num4, this.tr.forward * num4, Mathf.Clamp((!flag2) ? 1f : (this.distanceToWaypoint * 2f), 0f, 0.5f)); this.velocity.y = y; } else { this.velocity = VectorMath.ClampMagnitudeXZ(this.velocity, num2); } this.velocity += RichAI.deltaTime * this.gravity; if (this.rvoController != null && this.rvoController.enabled) { Vector3 pos = vector + VectorMath.ClampMagnitudeXZ(this.velocity, magnitude); this.rvoController.SetTarget(pos, VectorMath.MagnitudeXZ(this.velocity), this.maxSpeed); } Vector3 vector6; if (this.rvoController != null && this.rvoController.enabled) { vector6 = this.rvoController.CalculateMovementDelta(vector, RichAI.deltaTime); vector6.y = this.velocity.y * RichAI.deltaTime; } else { vector6 = this.velocity * RichAI.deltaTime; } if (flag2) { Vector3 trotdir = Vector3.Lerp(vector6.normalized, this.currentTargetDirection, Math.Max(1f - this.distanceToWaypoint * 2f, 0f)); this.RotateTowards(trotdir); } else { this.RotateTowards(vector6); } if (this.controller != null && this.controller.enabled) { this.tr.position = vector; this.controller.Move(vector6); vector = this.tr.position; } else { float y2 = vector.y; vector += vector6; vector = this.RaycastPosition(vector, y2); } Vector3 vector7 = richFunnel.ClampToNavmesh(vector); if (vector != vector7) { Vector3 vector8 = vector7 - vector; this.velocity -= vector8 * Vector3.Dot(vector8, this.velocity) / vector8.sqrMagnitude; if (this.rvoController != null && this.rvoController.enabled) { this.rvoController.SetCollisionNormal(vector8); } } this.tr.position = vector7; } else if (this.rvoController != null && this.rvoController.enabled) { this.rvoController.Move(Vector3.zero); } if (currentPart is RichSpecial && !this.traversingSpecialPath) { base.StartCoroutine(this.TraverseSpecial(currentPart as RichSpecial)); } } else if (this.rvoController != null && this.rvoController.enabled) { this.rvoController.Move(Vector3.zero); } else if (!(this.controller != null) || !this.controller.enabled) { this.tr.position = this.RaycastPosition(this.tr.position, this.tr.position.y); } }
void TraverseFunnel(RichFunnel fn, float deltaTime) { // Clamp the current position to the navmesh // and update the list of upcoming corners in the path // and store that in the 'nextCorners' variable float elevation; Vector2 position = movementPlane.ToPlane(UpdateTarget(fn), out elevation); // Only find nearby walls every 5th frame to improve performance if (Time.frameCount % 5 == 0 && wallForce > 0 && wallDist > 0) { wallBuffer.Clear(); fn.FindWalls(wallBuffer, wallDist); } // Target point Vector2 targetPoint = waypoint = movementPlane.ToPlane(nextCorners[0]); // Direction to target Vector2 dir = targetPoint - position; // Is the endpoint of the path (part) the current target point bool targetIsEndPoint = lastCorner && nextCorners.Count == 1; // Normalized direction to the target Vector2 normdir = VectorMath.Normalize(dir, out distanceToWaypoint); // Calculate force from walls Vector2 wallForceVector = CalculateWallForce(position, elevation, normdir); Vector2 targetVelocity; if (targetIsEndPoint) { targetVelocity = slowdownTime > 0 ? Vector2.zero : normdir * maxSpeed; // Reduce the wall avoidance force as we get closer to our target wallForceVector *= System.Math.Min(distanceToWaypoint / 0.5f, 1); if (distanceToWaypoint <= endReachedDistance) { // END REACHED NextPart(); } } else { var nextNextCorner = nextCorners.Count > 1 ? movementPlane.ToPlane(nextCorners[1]) : position + 2 * dir; targetVelocity = (nextNextCorner - targetPoint).normalized * maxSpeed; } Vector2 accel = MovementUtilities.CalculateAccelerationToReachPoint(targetPoint - position, targetVelocity, velocity2D, acceleration, maxSpeed); // Update the velocity using the acceleration velocity2D += (accel + wallForceVector * wallForce) * deltaTime; // Distance to the end of the path (as the crow flies) var distToEndOfPath = fn.DistanceToEndOfPath; var slowdownFactor = slowdownTime > 0 ? distToEndOfPath / (maxSpeed * slowdownTime) : 1; velocity2D = MovementUtilities.ClampVelocity(velocity2D, maxSpeed, slowdownFactor, slowWhenNotFacingTarget, movementPlane.ToPlane(tr.forward)); ApplyGravity(deltaTime); if (rvoController != null && rvoController.enabled) { // Send a message to the RVOController that we want to move // with this velocity. In the next simulation step, this // velocity will be processed and it will be fed back to the // rvo controller and finally it will be used by this script // when calling the CalculateMovementDelta method below // Make sure that we don't move further than to the end point // of the path. If the RVO simulation FPS is low and we did // not do this, the agent might overshoot the target a lot. var rvoTarget = movementPlane.ToWorld(position + Vector2.ClampMagnitude(velocity2D, distToEndOfPath), elevation); rvoController.SetTarget(rvoTarget, velocity2D.magnitude, maxSpeed); } // Direction and distance to move during this frame var deltaPosition = CalculateDeltaToMoveThisFrame(position, distToEndOfPath, deltaTime); // Rotate towards the direction we are moving in // Slow down the rotation of the character very close to the endpoint of the path to prevent oscillations var rotationSpeedFactor = targetIsEndPoint ? Mathf.Clamp01(1.1f * slowdownFactor - 0.1f) : 1f; RotateTowards(deltaPosition, rotationSpeed * rotationSpeedFactor * deltaTime); Move(movementPlane.ToWorld(position, elevation), movementPlane.ToWorld(deltaPosition, verticalVelocity * deltaTime)); }