public void Update() { #if FALSE // TODO: Not functional if (wallAvoidFalloff > 0 && wallAvoidForce > 0) { List <ObstacleVertex> obst = rvoAgent.NeighbourObstacles; if (obst != null) { for (int i = 0; i < obst.Count; i++) { Vector3 a = obst[i].position; Vector3 b = obst[i].next.position; Vector3 closest = position - VectorMath.ClosestPointOnSegment(a, b, position); if (closest == a || closest == b) { continue; } float dist = closest.sqrMagnitude; closest /= dist * wallAvoidFalloff; force += closest; } } } #endif }
public Vector3 GetMovementVector(Vector3 point) { if (vectorPath == null || vectorPath.Count == 0) { return(Vector3.zero); } if (vectorPath.Count == 1) { return(vectorPath[0] - point); } float minDist = float.PositiveInfinity; //Mathf.Infinity; int minSegment = 0; for (int i = 0; i < vectorPath.Count - 1; i++) { Vector3 closest = VectorMath.ClosestPointOnSegment(vectorPath[i], vectorPath[i + 1], point); float dist = (closest - point).sqrMagnitude; if (dist < minDist) { minDist = dist; minSegment = i; } } return(vectorPath[minSegment + 1] - point); }
public void Update() { if (this.rvoAgent == null) { return; } if (this.lastPosition != this.tr.position) { this.Teleport(this.tr.position); } if (this.lockWhenNotMoving) { this.locked = (this.desiredVelocity == Vector3.zero); } this.UpdateAgentProperties(); Vector3 interpolatedPosition = this.rvoAgent.InterpolatedPosition; interpolatedPosition.y = this.adjustedY; RaycastHit raycastHit; if (this.mask != 0 && Physics.Raycast(interpolatedPosition + Vector3.up * this.height * 0.5f, Vector3.down, out raycastHit, float.PositiveInfinity, this.mask)) { this.adjustedY = raycastHit.point.y; } else { this.adjustedY = 0f; } interpolatedPosition.y = this.adjustedY; this.rvoAgent.SetYPosition(this.adjustedY); Vector3 a = Vector3.zero; if (this.wallAvoidFalloff > 0f && this.wallAvoidForce > 0f) { List <ObstacleVertex> neighbourObstacles = this.rvoAgent.NeighbourObstacles; if (neighbourObstacles != null) { for (int i = 0; i < neighbourObstacles.Count; i++) { Vector3 position = neighbourObstacles[i].position; Vector3 position2 = neighbourObstacles[i].next.position; Vector3 vector = this.position - VectorMath.ClosestPointOnSegment(position, position2, this.position); if (!(vector == position) && !(vector == position2)) { float sqrMagnitude = vector.sqrMagnitude; vector /= sqrMagnitude * this.wallAvoidFalloff; a += vector; } } } } this.rvoAgent.DesiredVelocity = this.desiredVelocity + a * this.wallAvoidForce; this.tr.position = interpolatedPosition + Vector3.up * this.height * 0.5f - this.center; this.lastPosition = this.tr.position; if (this.enableRotation && this.velocity != Vector3.zero) { base.transform.rotation = Quaternion.Lerp(base.transform.rotation, Quaternion.LookRotation(this.velocity), Time.deltaTime * this.rotationSpeed * Mathf.Min(this.velocity.magnitude, 0.2f)); } }
public void Update() { if (this.rvoAgent != null) { RaycastHit hit; if (this.lastPosition != this.tr.position) { this.Teleport(this.tr.position); } if (this.lockWhenNotMoving) { this.locked = this.desiredVelocity == Vector3.zero; } this.UpdateAgentProperties(); Vector3 interpolatedPosition = this.rvoAgent.InterpolatedPosition; interpolatedPosition.y = this.adjustedY; if ((this.mask != 0) && Physics.Raycast(interpolatedPosition + ((Vector3)((Vector3.up * this.height) * 0.5f)), Vector3.down, out hit, float.PositiveInfinity, (int)this.mask)) { this.adjustedY = hit.point.y; } else { this.adjustedY = 0f; } interpolatedPosition.y = this.adjustedY; this.rvoAgent.SetYPosition(this.adjustedY); Vector3 zero = Vector3.zero; if ((this.wallAvoidFalloff > 0f) && (this.wallAvoidForce > 0f)) { List <ObstacleVertex> neighbourObstacles = this.rvoAgent.NeighbourObstacles; if (neighbourObstacles != null) { for (int i = 0; i < neighbourObstacles.Count; i++) { Vector3 position = neighbourObstacles[i].position; Vector3 lineEnd = neighbourObstacles[i].next.position; Vector3 vector5 = this.position - VectorMath.ClosestPointOnSegment(position, lineEnd, this.position); if ((vector5 != position) && (vector5 != lineEnd)) { float sqrMagnitude = vector5.sqrMagnitude; vector5 = (Vector3)(vector5 / (sqrMagnitude * this.wallAvoidFalloff)); zero += vector5; } } } } this.rvoAgent.DesiredVelocity = this.desiredVelocity + ((Vector3)(zero * this.wallAvoidForce)); this.tr.position = (interpolatedPosition + ((Vector3)((Vector3.up * this.height) * 0.5f))) - this.center; this.lastPosition = this.tr.position; if (this.enableRotation && (this.velocity != Vector3.zero)) { base.transform.rotation = Quaternion.Lerp(base.transform.rotation, Quaternion.LookRotation(this.velocity), (Time.deltaTime * this.rotationSpeed) * Mathf.Min(this.velocity.magnitude, 0.2f)); } } }
public static Agent.VO SegmentObstacle(Vector2 segmentStart, Vector2 segmentEnd, Vector2 offset, float radius, float inverseDt, float inverseDeltaTime) { Agent.VO result = default(Agent.VO); result.weightFactor = 1f; result.weightBonus = Mathf.Max(radius, 1f) * 40f; Vector3 vector = VectorMath.ClosestPointOnSegment(segmentStart, segmentEnd, Vector2.zero); if (vector.magnitude <= radius) { result.colliding = true; result.line1 = vector.normalized * (vector.magnitude - radius) * 0.3f * inverseDeltaTime; Vector2 vector2 = new Vector2(result.line1.y, -result.line1.x); result.dir1 = vector2.normalized; result.line1 += offset; result.cutoffDir = Vector2.zero; result.cutoffLine = Vector2.zero; result.dir2 = Vector2.zero; result.line2 = Vector2.zero; result.radius = 0f; result.segmentStart = Vector2.zero; result.segmentEnd = Vector2.zero; result.segment = false; } else { result.colliding = false; segmentStart *= inverseDt; segmentEnd *= inverseDt; radius *= inverseDt; Vector2 normalized = (segmentEnd - segmentStart).normalized; result.cutoffDir = normalized; result.cutoffLine = segmentStart + new Vector2(-normalized.y, normalized.x) * radius; result.cutoffLine += offset; float sqrMagnitude = segmentStart.sqrMagnitude; Vector2 a = -Agent.VO.ComplexMultiply(segmentStart, new Vector2(radius, Mathf.Sqrt(Mathf.Max(0f, sqrMagnitude - radius * radius)))) / sqrMagnitude; float sqrMagnitude2 = segmentEnd.sqrMagnitude; Vector2 a2 = -Agent.VO.ComplexMultiply(segmentEnd, new Vector2(radius, -Mathf.Sqrt(Mathf.Max(0f, sqrMagnitude2 - radius * radius)))) / sqrMagnitude2; result.line1 = segmentStart + a * radius + offset; result.line2 = segmentEnd + a2 * radius + offset; result.dir1 = new Vector2(a.y, -a.x); result.dir2 = new Vector2(a2.y, -a2.x); result.segmentStart = segmentStart; result.segmentEnd = segmentEnd; result.radius = radius; result.segment = true; } return(result); }
/// <summary> /// Gradient and value of the cost function of this VO. /// The VO has a cost function which is 0 outside the VO /// and increases inside it as the point moves further into /// the VO. /// /// This is the negative gradient of that function as well as its /// value (the weight). The negative gradient points in the direction /// where the function decreases the fastest. /// /// The value of the function is the distance to the closest edge /// of the VO and the gradient is normalized. /// </summary> public Vector2 Gradient(Vector2 p, out float weight) { if (colliding) { // Calculate double signed area of the triangle consisting of the points // {line1, line1+dir1, p} float l1 = SignedDistanceFromLine(line1, dir1, p); // Serves as a check for which side of the line the point p is if (l1 >= 0) { weight = l1; return(new Vector2(-dir1.y, dir1.x)); } else { weight = 0; return(new Vector2(0, 0)); } } float det3 = SignedDistanceFromLine(cutoffLine, cutoffDir, p); if (det3 <= 0) { weight = 0; return(Vector2.zero); } else { // Signed distances to the two edges along the sides of the VO float det1 = SignedDistanceFromLine(line1, dir1, p); float det2 = SignedDistanceFromLine(line2, dir2, p); if (det1 >= 0 && det2 >= 0) { // We are inside both of the half planes // (all three if we count the cutoff line) // and thus inside the forbidden region in velocity space // Actually the negative gradient because we want the // direction where it slopes the most downwards, not upwards Vector2 gradient; // Check if we are in the semicircle region near the cap of the VO if (Vector2.Dot(p - line1, dir1) > 0 && Vector2.Dot(p - line2, dir2) < 0) { if (segment) { // This part will only be reached for line obstacles (i.e not other agents) if (det3 < radius) { var closestPointOnLine = (Vector2)VectorMath.ClosestPointOnSegment(segmentStart, segmentEnd, p); var dirFromCenter = p - closestPointOnLine; float distToCenter; gradient = VectorMath.Normalize(dirFromCenter, out distToCenter); // The weight is the distance to the edge weight = radius - distToCenter; return(gradient); } } else { var dirFromCenter = p - circleCenter; float distToCenter; gradient = VectorMath.Normalize(dirFromCenter, out distToCenter); // The weight is the distance to the edge weight = radius - distToCenter; return(gradient); } } if (segment && det3 < det1 && det3 < det2) { weight = det3; gradient = new Vector2(-cutoffDir.y, cutoffDir.x); return(gradient); } // Just move towards the closest edge // The weight is the distance to the edge if (det1 < det2) { weight = det1; gradient = new Vector2(-dir1.y, dir1.x); } else { weight = det2; gradient = new Vector2(-dir2.y, dir2.x); } return(gradient); } weight = 0; return(Vector2.zero); } }
/// <summary> /// Creates a VO for avoiding another agent. /// Note that the segment is directed, the agent will want to be on the left side of the segment. /// </summary> public static VO SegmentObstacle(Vector2 segmentStart, Vector2 segmentEnd, Vector2 offset, float radius, float inverseDt, float inverseDeltaTime) { var vo = new VO(); // Adjusted so that a parameter weightFactor of 1 will be the default ("natural") weight factor vo.weightFactor = 1; // Just higher than anything else vo.weightBonus = Mathf.Max(radius, 1) * 40; var closestOnSegment = VectorMath.ClosestPointOnSegment(segmentStart, segmentEnd, Vector2.zero); // Collision? if (closestOnSegment.magnitude <= radius) { vo.colliding = true; vo.line1 = closestOnSegment.normalized * (closestOnSegment.magnitude - radius) * 0.3f * inverseDeltaTime; vo.dir1 = new Vector2(vo.line1.y, -vo.line1.x).normalized; vo.line1 += offset; vo.cutoffDir = Vector2.zero; vo.cutoffLine = Vector2.zero; vo.dir2 = Vector2.zero; vo.line2 = Vector2.zero; vo.radius = 0; vo.segmentStart = Vector2.zero; vo.segmentEnd = Vector2.zero; vo.segment = false; } else { vo.colliding = false; segmentStart *= inverseDt; segmentEnd *= inverseDt; radius *= inverseDt; var cutoffTangent = (segmentEnd - segmentStart).normalized; vo.cutoffDir = cutoffTangent; vo.cutoffLine = segmentStart + new Vector2(-cutoffTangent.y, cutoffTangent.x) * radius; vo.cutoffLine += offset; // See documentation for details // The call to Max is just to prevent floating point errors causing NaNs to appear var startSqrMagnitude = segmentStart.sqrMagnitude; var normal1 = -VectorMath.ComplexMultiply(segmentStart, new Vector2(radius, Mathf.Sqrt(Mathf.Max(0, startSqrMagnitude - radius * radius)))) / startSqrMagnitude; var endSqrMagnitude = segmentEnd.sqrMagnitude; var normal2 = -VectorMath.ComplexMultiply(segmentEnd, new Vector2(radius, -Mathf.Sqrt(Mathf.Max(0, endSqrMagnitude - radius * radius)))) / endSqrMagnitude; vo.line1 = segmentStart + normal1 * radius + offset; vo.line2 = segmentEnd + normal2 * radius + offset; // Note that the normals are already normalized vo.dir1 = new Vector2(normal1.y, -normal1.x); vo.dir2 = new Vector2(normal2.y, -normal2.x); vo.segmentStart = segmentStart; vo.segmentEnd = segmentEnd; vo.radius = radius; vo.segment = true; } return(vo); }
public Vector2 Gradient(Vector2 p, out float weight) { if (this.colliding) { float num = Agent.VO.SignedDistanceFromLine(this.line1, this.dir1, p); if (num >= 0f) { weight = num; return(new Vector2(-this.dir1.y, this.dir1.x)); } weight = 0f; return(new Vector2(0f, 0f)); } else { float num2 = Agent.VO.SignedDistanceFromLine(this.cutoffLine, this.cutoffDir, p); if (num2 <= 0f) { weight = 0f; return(Vector2.zero); } float num3 = Agent.VO.SignedDistanceFromLine(this.line1, this.dir1, p); float num4 = Agent.VO.SignedDistanceFromLine(this.line2, this.dir2, p); if (num3 < 0f || num4 < 0f) { weight = 0f; return(Vector2.zero); } Vector2 result; if (Vector2.Dot(p - this.line1, this.dir1) > 0f && Vector2.Dot(p - this.line2, this.dir2) < 0f) { if (!this.segment) { float num5; result = VectorMath.Normalize(p - this.circleCenter, out num5); weight = this.radius - num5; return(result); } if (num2 < this.radius) { Vector2 b = VectorMath.ClosestPointOnSegment(this.segmentStart, this.segmentEnd, p); float num6; result = VectorMath.Normalize(p - b, out num6); weight = this.radius - num6; return(result); } } if (this.segment && num2 < num3 && num2 < num4) { weight = num2; result = new Vector2(-this.cutoffDir.y, this.cutoffDir.x); return(result); } if (num3 < num4) { weight = num3; result = new Vector2(-this.dir1.y, this.dir1.x); } else { weight = num4; result = new Vector2(-this.dir2.y, this.dir2.x); } return(result); } }
public void Update() { if (!GameEngine.Instance.IsTimeToRootScene) { return; } //如果是副本中则不能进入rvo if (LTInstanceMapModel.Instance.IsInstanceMap()) { return; } if (rvoAgent == null) { return; } if (lastPosition != tr.position) { Teleport(tr.position); } if (lockWhenNotMoving) { locked = desiredVelocity == Vector3.zero; } UpdateAgentProperties(); RaycastHit hit; //The non-interpolated position Vector3 realPos = rvoAgent.InterpolatedPosition; realPos.y = adjustedY; if (mask != 0 && Physics.Raycast(realPos + Vector3.up * height * 0.5f, Vector3.down, out hit, float.PositiveInfinity, mask)) { adjustedY = hit.point.y; } else { adjustedY = 0; } realPos.y = adjustedY; rvoAgent.SetYPosition(adjustedY); Vector3 force = Vector3.zero; if (wallAvoidFalloff > 0 && wallAvoidForce > 0) { List <ObstacleVertex> obst = rvoAgent.NeighbourObstacles; if (obst != null) { for (int i = 0; i < obst.Count; i++) { Vector3 a = obst[i].position; Vector3 b = obst[i].next.position; Vector3 closest = position - VectorMath.ClosestPointOnSegment(a, b, position); if (closest == a || closest == b) { continue; } float dist = closest.sqrMagnitude; closest /= dist * wallAvoidFalloff; force += closest; } } } #if ASTARDEBUG Debug.DrawRay(position, desiredVelocity + force * wallAvoidForce); #endif rvoAgent.DesiredVelocity = desiredVelocity + force * wallAvoidForce; tr.position = realPos + Vector3.up * height * 0.5f - center; lastPosition = tr.position; if (enableRotation && velocity != Vector3.zero) { transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(velocity), Time.deltaTime * rotationSpeed * Mathf.Min(velocity.magnitude, 0.2f)); } }
/// <summary>Update is called once per frame</summary> protected override void OnUpdate(float dt) { deltaTime = dt; if (richPath != null) { //System.Diagnostics.Stopwatch w = new System.Diagnostics.Stopwatch(); //w.Start(); RichPathPart pt = richPath.GetCurrentPart(); var 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 && wallForce > 0 && wallDist > 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 = nextCorners[tgIndex]; Vector3 dir = tg - position; dir.y = 0; bool passedTarget = Vector3.Dot(dir, currentTargetDirection) < 0; //Check if passed target in another way if (passedTarget && nextCorners.Count - tgIndex > 1) { tgIndex++; tg = nextCorners[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 distanceToSteeringTarget = 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 = VectorMath.ClosestPointOnSegment(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 && nextCorners.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) { if (!traversingOffMeshLink) { StartCoroutine(TraverseSpecial(pt as RichSpecial)); } } //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); } } UpdateVelocity(); lastDeltaTime = dt; }
// Token: 0x0600276A RID: 10090 RVA: 0x001AE518 File Offset: 0x001AC718 protected override void Update() { LegacyRichAI.deltaTime = Mathf.Min(Time.smoothDeltaTime * 2f, Time.deltaTime); if (this.richPath != null) { RichPathPart currentPart = this.richPath.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; if (Vector3.Dot(vector3, this.currentTargetDirection) < 0f && 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; float magnitude = vector3.magnitude; this.distanceToSteeringTarget = magnitude; vector3 = ((magnitude == 0f) ? Vector3.zero : (vector3 / magnitude)); Vector3 lhs = vector3; Vector3 a = 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) { float sqrMagnitude = (VectorMath.ClosestPointOnSegment(this.wallBuffer[i], this.wallBuffer[i + 1], this.tr.position) - 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); } } } a = Vector3.Cross(Vector3.up, vector3) * (num3 - num2); } bool flag = this.lastCorner && this.nextCorners.Count - num == 1; if (flag) { if (this.slowdownTime < 0.001f) { this.slowdownTime = 0.001f; } Vector3 a2 = vector2 - vector; a2.y = 0f; if (this.preciseSlowdown) { vector3 = (6f * a2 - 4f * this.slowdownTime * this.velocity) / (this.slowdownTime * this.slowdownTime); } else { vector3 = 2f * (a2 - this.slowdownTime * this.velocity) / (this.slowdownTime * this.slowdownTime); } vector3 = Vector3.ClampMagnitude(vector3, this.acceleration); a *= Math.Min(magnitude / 0.5f, 1f); if (magnitude < this.endReachedDistance) { base.NextPart(); } } else { vector3 *= this.acceleration; } this.velocity += (vector3 + a * this.wallForce) * LegacyRichAI.deltaTime; if (this.slowWhenNotFacingTarget) { float a3 = (Vector3.Dot(lhs, this.tr.forward) + 0.5f) * 0.6666667f; float a4 = Mathf.Sqrt(this.velocity.x * this.velocity.x + this.velocity.z * this.velocity.z); float y = this.velocity.y; this.velocity.y = 0f; float d = Mathf.Min(a4, this.maxSpeed * Mathf.Max(a3, 0.2f)); this.velocity = Vector3.Lerp(this.tr.forward * d, this.velocity.normalized * d, Mathf.Clamp(flag ? (magnitude * 2f) : 0f, 0.5f, 1f)); this.velocity.y = y; } else { float num5 = Mathf.Sqrt(this.velocity.x * this.velocity.x + this.velocity.z * this.velocity.z); num5 = this.maxSpeed / num5; if (num5 < 1f) { this.velocity.x = this.velocity.x * num5; this.velocity.z = this.velocity.z * num5; } } if (flag) { Vector3 trotdir = Vector3.Lerp(this.velocity, this.currentTargetDirection, Math.Max(1f - magnitude * 2f, 0f)); this.RotateTowards(trotdir); } else { this.RotateTowards(this.velocity); } this.velocity += LegacyRichAI.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 * LegacyRichAI.deltaTime); } else { float y2 = vector.y; vector += this.velocity * LegacyRichAI.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 && !base.traversingOffMeshLink) { 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); } base.UpdateVelocity(); this.lastDeltaTime = Time.deltaTime; }