Esempio n. 1
0
        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
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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));
            }
        }
Esempio n. 4
0
 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));
         }
     }
 }
Esempio n. 5
0
            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);
            }
Esempio n. 6
0
            /// <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);
                }
            }
Esempio n. 7
0
            /// <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);
            }
Esempio n. 8
0
 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);
     }
 }
Esempio n. 9
0
        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));
            }
        }
Esempio n. 10
0
        /// <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;
 }