Inheritance: RichPathPart
Esempio n. 1
0
        // Token: 0x0600217B RID: 8571 RVA: 0x0018E3AC File Offset: 0x0018C5AC
        protected override void MovementUpdateInternal(float deltaTime, out Vector3 nextPosition, out Quaternion nextRotation)
        {
            if (this.updatePosition)
            {
                this.simulatedPosition = this.tr.position;
            }
            if (this.updateRotation)
            {
                this.simulatedRotation = this.tr.rotation;
            }
            RichPathPart currentPart = this.richPath.GetCurrentPart();

            if (currentPart is RichSpecial)
            {
                if (!this.traversingOffMeshLink)
                {
                    base.StartCoroutine(this.TraverseSpecial(currentPart as RichSpecial));
                }
                nextPosition = (this.steeringTarget = this.simulatedPosition);
                nextRotation = base.rotation;
                return;
            }
            RichFunnel richFunnel = currentPart as RichFunnel;

            if (richFunnel != null && !base.isStopped)
            {
                this.TraverseFunnel(richFunnel, deltaTime, out nextPosition, out nextRotation);
                return;
            }
            this.velocity2D -= Vector2.ClampMagnitude(this.velocity2D, this.acceleration * deltaTime);
            this.FinalMovement(this.simulatedPosition, deltaTime, float.PositiveInfinity, 1f, out nextPosition, out nextRotation);
            this.steeringTarget = this.simulatedPosition;
        }
Esempio n. 2
0
 private void OnPathComplete(Path p)
 {
     this.waitingForPathCalc = false;
     p.Claim(this);
     if (p.error)
     {
         p.Release(this, false);
         return;
     }
     if (this.traversingSpecialPath)
     {
         this.delayUpdatePath = true;
     }
     else
     {
         this.richPath.Initialize(this.seeker, p, true, this.funnelSimplification);
         RichFunnel richFunnel = this.richPath.GetCurrentPart() as RichFunnel;
         if (richFunnel != null)
         {
             Vector2 b = this.movementPlane.ToPlane(this.UpdateTarget(richFunnel));
             if (this.lastCorner && this.nextCorners.Count == 1)
             {
                 Vector2 a = this.waypoint = this.movementPlane.ToPlane(this.nextCorners[0]);
                 this.distanceToWaypoint = (a - b).magnitude;
                 if (this.distanceToWaypoint <= this.endReachedDistance)
                 {
                     this.NextPart();
                 }
             }
         }
     }
     p.Release(this, false);
 }
Esempio n. 3
0
        protected override void MovementUpdate(float deltaTime)
        {
            RichPathPart currentPart = this.richPath.GetCurrentPart();
            RichFunnel   richFunnel  = currentPart as RichFunnel;

            if (richFunnel != null)
            {
                this.TraverseFunnel(richFunnel, deltaTime);
            }
            else if (currentPart is RichSpecial)
            {
                if (!this.traversingSpecialPath)
                {
                    base.StartCoroutine(this.TraverseSpecial(currentPart as RichSpecial));
                }
            }
            else
            {
                if (this.rvoController != null && this.rvoController.enabled)
                {
                    this.rvoController.Move(Vector3.zero);
                }
                base.Move(this.tr.position, Vector3.zero);
            }
            Vector3 position = this.tr.position;

            this.realVelocity = ((deltaTime > 0f) ? ((position - this.prevPosition) / deltaTime) : Vector3.zero);
            this.prevPosition = position;
        }
Esempio n. 4
0
 // Token: 0x0600217E RID: 8574 RVA: 0x0018E818 File Offset: 0x0018CA18
 protected override Vector3 ClampToNavmesh(Vector3 position, out bool positionChanged)
 {
     if (this.richPath != null)
     {
         RichFunnel richFunnel = this.richPath.GetCurrentPart() as RichFunnel;
         if (richFunnel != null)
         {
             Vector3 a            = richFunnel.ClampToNavmesh(position);
             Vector2 vector       = this.movementPlane.ToPlane(a - position);
             float   sqrMagnitude = vector.sqrMagnitude;
             if (sqrMagnitude > 1.00000011E-06f)
             {
                 this.velocity2D -= vector * Vector2.Dot(vector, this.velocity2D) / sqrMagnitude;
                 if (this.rvoController != null && this.rvoController.enabled)
                 {
                     this.rvoController.SetCollisionNormal(vector);
                 }
                 positionChanged = true;
                 return(position + this.movementPlane.ToWorld(vector, 0f));
             }
         }
     }
     positionChanged = false;
     return(position);
 }
Esempio n. 5
0
        protected override Vector3 UpdateTarget(RichFunnel fn)
        {
            Matrix4x4 matrix  = this.graph.GetMatrix();
            Matrix4x4 inverse = matrix.inverse;

            Debug.DrawRay(matrix.MultiplyPoint3x4(this.tr.position), Vector3.up * 2f, Color.red);
            Debug.DrawRay(inverse.MultiplyPoint3x4(this.tr.position), Vector3.up * 2f, Color.green);
            this.nextCorners.Clear();
            Vector3 vector  = this.tr.position;
            Vector3 vector2 = matrix.MultiplyPoint3x4(vector);
            bool    flag;

            vector2 = fn.Update(vector2, this.nextCorners, 2, out this.lastCorner, out flag);
            vector  = inverse.MultiplyPoint3x4(vector2);
            Debug.DrawRay(vector, Vector3.up * 3f, Color.black);
            for (int i = 0; i < this.nextCorners.Count; i++)
            {
                this.nextCorners[i] = inverse.MultiplyPoint3x4(this.nextCorners[i]);
                Debug.DrawRay(this.nextCorners[i], Vector3.up * 3f, Color.yellow);
            }
            if (flag && !this.waitingForPathCalc)
            {
                this.UpdatePath();
            }
            return(vector);
        }
Esempio n. 6
0
	protected override Vector3 UpdateTarget (RichFunnel fn) {
		Matrix4x4 m = graph.GetMatrix();
		Matrix4x4 mi = m.inverse;


		Debug.DrawRay(m.MultiplyPoint3x4(tr.position), Vector3.up*2, Color.red);
		Debug.DrawRay(mi.MultiplyPoint3x4(tr.position), Vector3.up*2, Color.green);

		buffer.Clear();

		/* Current position. We read and write to tr.position as few times as possible since doing so
		 * is much slower than to read and write from/to a local variable
		 */
		Vector3 position = tr.position;
		bool requiresRepath;

		// Update, but first convert our position to graph space, then convert the result back to world space
		var positionInGraphSpace = m.MultiplyPoint3x4(position);
		positionInGraphSpace = fn.Update(positionInGraphSpace, buffer, 2, out lastCorner, out requiresRepath);
		position = mi.MultiplyPoint3x4(positionInGraphSpace);

		Debug.DrawRay(position, Vector3.up*3, Color.black);

		// convert the result to world space from graph space
		for (int i = 0; i < buffer.Count; i++) {
			buffer[i] = mi.MultiplyPoint3x4(buffer[i]);
			Debug.DrawRay(buffer[i], Vector3.up*3, Color.yellow);
		}

		if (requiresRepath && !waitingForPathCalc) {
			UpdatePath();
		}

		return position;
	}
Esempio n. 7
0
        public static void SimplifyPath2(IRaycastableGraph rcg, List <GraphNode> nodes, int start, int end, List <GraphNode> result, Vector3 startPoint, Vector3 endPoint)
        {
            int count = result.Count;

            if (end <= start + 1)
            {
                result.Add(nodes[start]);
                result.Add(nodes[end]);
                return;
            }
            GraphHitInfo graphHitInfo;

            if (rcg.Linecast(startPoint, endPoint, nodes[start], out graphHitInfo, result) || result[result.Count - 1] != nodes[end])
            {
                result.RemoveRange(count, result.Count - count);
                int   num  = -1;
                float num2 = float.PositiveInfinity;
                for (int i = start + 1; i < end; i++)
                {
                    float num3 = AstarMath.DistancePointSegmentStrict(startPoint, endPoint, (Vector3)nodes[i].position);
                    if (num == -1 || num3 < num2)
                    {
                        num  = i;
                        num2 = num3;
                    }
                }
                RichFunnel.SimplifyPath2(rcg, nodes, start, num, result, startPoint, (Vector3)nodes[num].position);
                result.RemoveAt(result.Count - 1);
                RichFunnel.SimplifyPath2(rcg, nodes, num, end, result, (Vector3)nodes[num].position, endPoint);
            }
        }
        protected override Vector3 UpdateTarget(RichFunnel fn)
        {
            bool      flag;
            Matrix4x4 matrix  = this.graph.GetMatrix();
            Matrix4x4 inverse = matrix.inverse;

            Debug.DrawRay(matrix.MultiplyPoint3x4(base.tr.position), (Vector3)(Vector3.up * 2f), Color.red);
            Debug.DrawRay(inverse.MultiplyPoint3x4(base.tr.position), (Vector3)(Vector3.up * 2f), Color.green);
            base.buffer.Clear();
            Vector3 position = base.tr.position;
            Vector3 vector2  = matrix.MultiplyPoint3x4(position);

            vector2  = fn.Update(vector2, base.buffer, 2, out this.lastCorner, out flag);
            position = inverse.MultiplyPoint3x4(vector2);
            Debug.DrawRay(position, (Vector3)(Vector3.up * 3f), Color.black);
            for (int i = 0; i < base.buffer.Count; i++)
            {
                base.buffer[i] = inverse.MultiplyPoint3x4(base.buffer[i]);
                Debug.DrawRay(base.buffer[i], (Vector3)(Vector3.up * 3f), Color.yellow);
            }
            if (flag && !base.waitingForPathCalc)
            {
                this.UpdatePath();
            }
            return(position);
        }
        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);
        }
Esempio n. 10
0
		protected virtual Vector3 UpdateTarget(RichFunnel fn)
		{
			this.nextCorners.Clear();
			Vector3 vector = this.tr.position;
			bool flag;
			vector = fn.Update(vector, this.nextCorners, 2, out this.lastCorner, out flag);
			if (flag && !this.waitingForPathCalc)
			{
				this.UpdatePath();
			}
			return vector;
		}
Esempio n. 11
0
 protected override Vector3 ClampToNavmesh(Vector3 position)
 {
     if (this.richPath != null)
     {
         RichFunnel richFunnel = this.richPath.GetCurrentPart() as RichFunnel;
         if (richFunnel != null)
         {
             return(richFunnel.ClampToNavmesh(position));
         }
     }
     return(position);
 }
Esempio n. 12
0
        // Token: 0x0600217A RID: 8570 RVA: 0x0018E360 File Offset: 0x0018C560
        protected virtual Vector3 UpdateTarget(RichFunnel fn)
        {
            this.nextCorners.Clear();
            bool    flag;
            Vector3 result = fn.Update(this.simulatedPosition, this.nextCorners, 2, out this.lastCorner, out flag);

            if (flag && !this.waitingForPathCalculation && this.canSearch)
            {
                this.SearchPath();
            }
            return(result);
        }
Esempio n. 13
0
        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));
        }
Esempio n. 14
0
        public static void SimplifyPath3(IRaycastableGraph rcg, List <GraphNode> nodes, int start, int end, List <GraphNode> result, Vector3 startPoint, Vector3 endPoint, int depth = 0)
        {
            if (start == end)
            {
                result.Add(nodes[start]);
                return;
            }
            if (start + 1 == end)
            {
                result.Add(nodes[start]);
                result.Add(nodes[end]);
                return;
            }
            int          count = result.Count;
            GraphHitInfo graphHitInfo;

            if (rcg.Linecast(startPoint, endPoint, nodes[start], out graphHitInfo, result) || result[result.Count - 1] != nodes[end])
            {
                result.RemoveRange(count, result.Count - count);
                int   num  = 0;
                float num2 = 0f;
                for (int i = start + 1; i < end - 1; i++)
                {
                    float num3 = AstarMath.DistancePointSegmentStrict(startPoint, endPoint, (Vector3)nodes[i].position);
                    if (num3 > num2)
                    {
                        num  = i;
                        num2 = num3;
                    }
                }
                int num4 = (num + start) / 2;
                int num5 = (num + end) / 2;
                if (num4 == num5)
                {
                    RichFunnel.SimplifyPath3(rcg, nodes, start, num4, result, startPoint, (Vector3)nodes[num4].position, 0);
                    result.RemoveAt(result.Count - 1);
                    RichFunnel.SimplifyPath3(rcg, nodes, num4, end, result, (Vector3)nodes[num4].position, endPoint, depth + 1);
                }
                else
                {
                    RichFunnel.SimplifyPath3(rcg, nodes, start, num4, result, startPoint, (Vector3)nodes[num4].position, depth + 1);
                    result.RemoveAt(result.Count - 1);
                    RichFunnel.SimplifyPath3(rcg, nodes, num4, num5, result, (Vector3)nodes[num4].position, (Vector3)nodes[num5].position, depth + 1);
                    result.RemoveAt(result.Count - 1);
                    RichFunnel.SimplifyPath3(rcg, nodes, num5, end, result, (Vector3)nodes[num5].position, endPoint, depth + 1);
                }
            }
        }
Esempio n. 15
0
        protected virtual Vector3 UpdateTarget(RichFunnel fn)
        {
            nextCorners.Clear();

            // Current position. We read and write to tr.position as few times as possible since doing so
            // is much slower than to read and write from/to a local variable
            bool    requiresRepath;
            Vector3 position = fn.Update(tr.position, nextCorners, 2, out lastCorner, out requiresRepath);

            if (requiresRepath && !waitingForPathCalc)
            {
                UpdatePath();
            }

            return(position);
        }
        protected virtual Vector3 UpdateTarget(RichFunnel fn)
        {
            nextCorners.Clear();

            // This method assumes simulatedPosition is up to date as our current position.
            // We read and write to tr.position as few times as possible since doing so
            // is much slower than to read and write from/to a local/member variable.
            bool    requiresRepath;
            Vector3 position = fn.Update(simulatedPosition, nextCorners, 2, out lastCorner, out requiresRepath);

            if (requiresRepath && !waitingForPathCalculation && canSearch)
            {
                // TODO: What if canSearch is false? How do we notify other scripts that might be handling the path calculation that a new path needs to be calculated?
                SearchPath();
            }

            return(position);
        }
Esempio n. 17
0
        // 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);
        }
Esempio n. 18
0
 // Token: 0x06002177 RID: 8567 RVA: 0x0018E20C File Offset: 0x0018C40C
 protected override void OnPathComplete(Path p)
 {
     this.waitingForPathCalculation = false;
     p.Claim(this);
     if (p.error)
     {
         p.Release(this, false);
         return;
     }
     if (this.traversingOffMeshLink)
     {
         this.delayUpdatePath = true;
     }
     else
     {
         this.richPath.Initialize(this.seeker, p, true, this.funnelSimplification);
         RichFunnel richFunnel = this.richPath.GetCurrentPart() as RichFunnel;
         if (richFunnel != null)
         {
             if (this.updatePosition)
             {
                 this.simulatedPosition = this.tr.position;
             }
             Vector2 b = this.movementPlane.ToPlane(this.UpdateTarget(richFunnel));
             if (this.lastCorner && this.nextCorners.Count == 1)
             {
                 this.steeringTarget = this.nextCorners[0];
                 Vector2 a = this.movementPlane.ToPlane(this.steeringTarget);
                 this.distanceToSteeringTarget = (a - b).magnitude;
                 if (this.distanceToSteeringTarget <= this.endReachedDistance)
                 {
                     this.NextPart();
                 }
             }
         }
     }
     p.Release(this, false);
 }
Esempio n. 19
0
        // Token: 0x06002140 RID: 8512 RVA: 0x001890A0 File Offset: 0x001872A0
        public void Initialize(Seeker seeker, Path path, bool mergePartEndpoints, bool simplificationMode)
        {
            if (path.error)
            {
                throw new ArgumentException("Path has an error");
            }
            List <GraphNode> path2 = path.path;

            if (path2.Count == 0)
            {
                throw new ArgumentException("Path traverses no nodes");
            }
            this.seeker = seeker;
            for (int i = 0; i < this.parts.Count; i++)
            {
                RichFunnel  richFunnel  = this.parts[i] as RichFunnel;
                RichSpecial richSpecial = this.parts[i] as RichSpecial;
                if (richFunnel != null)
                {
                    ObjectPool <RichFunnel> .Release(ref richFunnel);
                }
                else if (richSpecial != null)
                {
                    ObjectPool <RichSpecial> .Release(ref richSpecial);
                }
            }
            this.Clear();
            this.Endpoint = path.vectorPath[path.vectorPath.Count - 1];
            for (int j = 0; j < path2.Count; j++)
            {
                if (path2[j] is TriangleMeshNode)
                {
                    NavmeshBase navmeshBase = AstarData.GetGraph(path2[j]) as NavmeshBase;
                    if (navmeshBase == null)
                    {
                        throw new Exception("Found a TriangleMeshNode that was not in a NavmeshBase graph");
                    }
                    RichFunnel richFunnel2 = ObjectPool <RichFunnel> .Claim().Initialize(this, navmeshBase);

                    richFunnel2.funnelSimplification = simplificationMode;
                    int  num        = j;
                    uint graphIndex = path2[num].GraphIndex;
                    while (j < path2.Count && (path2[j].GraphIndex == graphIndex || path2[j] is NodeLink3Node))
                    {
                        j++;
                    }
                    j--;
                    if (num == 0)
                    {
                        richFunnel2.exactStart = path.vectorPath[0];
                    }
                    else
                    {
                        richFunnel2.exactStart = (Vector3)path2[mergePartEndpoints ? (num - 1) : num].position;
                    }
                    if (j == path2.Count - 1)
                    {
                        richFunnel2.exactEnd = path.vectorPath[path.vectorPath.Count - 1];
                    }
                    else
                    {
                        richFunnel2.exactEnd = (Vector3)path2[mergePartEndpoints ? (j + 1) : j].position;
                    }
                    richFunnel2.BuildFunnelCorridor(path2, num, j);
                    this.parts.Add(richFunnel2);
                }
                else if (NodeLink2.GetNodeLink(path2[j]) != null)
                {
                    NodeLink2 nodeLink    = NodeLink2.GetNodeLink(path2[j]);
                    int       num2        = j;
                    uint      graphIndex2 = path2[num2].GraphIndex;
                    j++;
                    while (j < path2.Count && path2[j].GraphIndex == graphIndex2)
                    {
                        j++;
                    }
                    j--;
                    if (j - num2 > 1)
                    {
                        throw new Exception("NodeLink2 path length greater than two (2) nodes. " + (j - num2));
                    }
                    if (j - num2 != 0)
                    {
                        RichSpecial item = ObjectPool <RichSpecial> .Claim().Initialize(nodeLink, path2[num2]);

                        this.parts.Add(item);
                    }
                }
            }
        }
Esempio n. 20
0
        // Token: 0x06000033 RID: 51 RVA: 0x0000417C File Offset: 0x0000257C
        public void Initialize(Seeker s, Path p, bool mergePartEndpoints, RichFunnel.FunnelSimplification simplificationMode)
        {
            if (p.error)
            {
                throw new ArgumentException("Path has an error");
            }
            List <GraphNode> path = p.path;

            if (path.Count == 0)
            {
                throw new ArgumentException("Path traverses no nodes");
            }
            this.seeker = s;
            for (int i = 0; i < this.parts.Count; i++)
            {
                if (this.parts[i] is RichFunnel)
                {
                    ObjectPool <RichFunnel> .Release(this.parts[i] as RichFunnel);
                }
                else if (this.parts[i] is RichSpecial)
                {
                    ObjectPool <RichSpecial> .Release(this.parts[i] as RichSpecial);
                }
            }
            this.parts.Clear();
            this.currentPart = 0;
            for (int j = 0; j < path.Count; j++)
            {
                if (path[j] is TriangleMeshNode)
                {
                    IFunnelGraph graph      = AstarData.GetGraph(path[j]) as IFunnelGraph;
                    RichFunnel   richFunnel = ObjectPool <RichFunnel> .Claim().Initialize(this, graph);

                    richFunnel.funnelSimplificationMode = simplificationMode;
                    int  num        = j;
                    uint graphIndex = path[num].GraphIndex;
                    while (j < path.Count)
                    {
                        if (path[j].GraphIndex != graphIndex && !(path[j] is NodeLink3Node))
                        {
                            break;
                        }
                        j++;
                    }
                    j--;
                    if (num == 0)
                    {
                        richFunnel.exactStart = p.vectorPath[0];
                    }
                    else if (mergePartEndpoints)
                    {
                        richFunnel.exactStart = (Vector3)path[num - 1].position;
                    }
                    else
                    {
                        richFunnel.exactStart = (Vector3)path[num].position;
                    }
                    if (j == path.Count - 1)
                    {
                        richFunnel.exactEnd = p.vectorPath[p.vectorPath.Count - 1];
                    }
                    else if (mergePartEndpoints)
                    {
                        richFunnel.exactEnd = (Vector3)path[j + 1].position;
                    }
                    else
                    {
                        richFunnel.exactEnd = (Vector3)path[j].position;
                    }
                    richFunnel.BuildFunnelCorridor(path, num, j);
                    this.parts.Add(richFunnel);
                }
                else if (path[j] != null && NodeLink2.GetNodeLink(path[j]) != null)
                {
                    NodeLink2 nodeLink    = NodeLink2.GetNodeLink(path[j]);
                    int       num2        = j;
                    uint      graphIndex2 = path[num2].GraphIndex;
                    for (j++; j < path.Count; j++)
                    {
                        if (path[j].GraphIndex != graphIndex2)
                        {
                            break;
                        }
                    }
                    j--;
                    if (j - num2 > 1)
                    {
                        throw new Exception("NodeLink2 path length greater than two (2) nodes. " + (j - num2));
                    }
                    if (j - num2 != 0)
                    {
                        RichSpecial item = ObjectPool <RichSpecial> .Claim().Initialize(nodeLink, path[num2]);

                        this.parts.Add(item);
                    }
                }
            }
        }
Esempio n. 21
0
 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);
     }
 }
Esempio n. 22
0
		/** Use this for initialization.
		 *
		 * \param s Optionally provide in order to take tag penalties into account. May be null if you do not use a Seeker\
		 * \param p Path to follow
		 * \param mergePartEndpoints If true, then adjacent parts that the path is split up in will
		 * try to use the same start/end points. For example when using a link on a navmesh graph
		 * Instead of first following the path to the center of the node where the link is and then
		 * follow the link, the path will be adjusted to go to the exact point where the link starts
		 * which usually makes more sense.
		 * \param simplificationMode The path can optionally be simplified. This can be a bit expensive for long paths.
		 */
		public void Initialize (Seeker s, Path p, bool mergePartEndpoints, RichFunnel.FunnelSimplification simplificationMode) {

			if (p.error) throw new System.ArgumentException ("Path has an error");

			List<GraphNode> nodes = p.path;
			if (nodes.Count == 0) throw new System.ArgumentException ("Path traverses no nodes");

			seeker = s;
			// Release objects back to object pool
			// Yeah, I know, it's casting... but this won't be called much
			for (int i=0;i<parts.Count;i++) {
				     if (parts[i] is RichFunnel) ObjectPool<RichFunnel>.Release (parts[i] as RichFunnel);
				else if (parts[i] is RichSpecial) ObjectPool<RichSpecial>.Release (parts[i] as RichSpecial);
			}

			parts.Clear();
			currentPart = 0;

			// Initialize new

			//Break path into parts
			for (int i=0;i<nodes.Count;i++) {
				if (nodes[i] is TriangleMeshNode) {
					var funnelGraph = AstarData.GetGraph (nodes[i]) as IFunnelGraph;

					RichFunnel f = ObjectPool<RichFunnel>.Claim ().Initialize (this, funnelGraph);

					f.funnelSimplificationMode = simplificationMode;

					int sIndex = i;
					uint currentGraphIndex = nodes[sIndex].GraphIndex;


					for (; i < nodes.Count; i++) {
						if (nodes[i].GraphIndex != currentGraphIndex && !(nodes[i] is NodeLink3Node) ) {
							break;
						}
					}
					i--;

					if (sIndex == 0) {
						f.exactStart = p.vectorPath[0];
					} else {
						f.exactStart = (Vector3)nodes[mergePartEndpoints ? sIndex-1 : sIndex].position;
					}

					if (i == nodes.Count-1) {
						f.exactEnd = p.vectorPath[p.vectorPath.Count-1];
					} else {
						f.exactEnd = (Vector3)nodes[mergePartEndpoints ? i+1 : i].position;
					}

					f.BuildFunnelCorridor (nodes, sIndex, i);

					parts.Add (f);
				} else if (NodeLink2.GetNodeLink(nodes[i]) != null) {

					NodeLink2 nl = NodeLink2.GetNodeLink(nodes[i]);

					int sIndex = i;
					uint currentGraphIndex = nodes[sIndex].GraphIndex;

					for (i++; i < nodes.Count; i++) {
						if (nodes[i].GraphIndex != currentGraphIndex) {
							break;
						}
					}
					i--;

					if (i - sIndex > 1) {
						throw new System.Exception("NodeLink2 path length greater than two (2) nodes. " + (i - sIndex));
					} else if (i - sIndex == 0) {
						//Just continue, it might be the case that a NodeLink was the closest node
						continue;
					}

					RichSpecial rps = ObjectPool<RichSpecial>.Claim().Initialize (nl, nodes[sIndex]);
					parts.Add(rps);
				}
			}
		}
Esempio n. 23
0
		protected virtual Vector3 UpdateTarget ( RichFunnel fn ) {
			buffer.Clear ();
			/* Current position. We read and write to tr.position as few times as possible since doing so
			 * is much slower than to read and write from/to a local variable
			 */
			Vector3 position = tr.position;
			bool requiresRepath;
			position = fn.Update (position, buffer, 2, out lastCorner, out requiresRepath);
	
			if (requiresRepath && !waitingForPathCalc) {
				UpdatePath ();
			}
	
			return position;
		}
Esempio n. 24
0
        /** 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);
                }
            }
        }
Esempio n. 25
0
        public void BuildFunnelCorridor(List <GraphNode> nodes, int start, int end)
        {
            this.exactStart = (nodes[start] as MeshNode).ClosestPointOnNode(this.exactStart);
            this.exactEnd   = (nodes[end] as MeshNode).ClosestPointOnNode(this.exactEnd);
            this.left.Clear();
            this.right.Clear();
            this.left.Add(this.exactStart);
            this.right.Add(this.exactStart);
            this.nodes.Clear();
            IRaycastableGraph raycastableGraph = this.graph as IRaycastableGraph;

            if (raycastableGraph != null && this.funnelSimplificationMode != RichFunnel.FunnelSimplification.None)
            {
                List <GraphNode> list = ListPool <GraphNode> .Claim(end - start);

                switch (this.funnelSimplificationMode)
                {
                case RichFunnel.FunnelSimplification.Iterative:
                    this.SimplifyPath(raycastableGraph, nodes, start, end, list, this.exactStart, this.exactEnd);
                    break;

                case RichFunnel.FunnelSimplification.RecursiveBinary:
                    RichFunnel.SimplifyPath2(raycastableGraph, nodes, start, end, list, this.exactStart, this.exactEnd);
                    break;

                case RichFunnel.FunnelSimplification.RecursiveTrinary:
                    RichFunnel.SimplifyPath3(raycastableGraph, nodes, start, end, list, this.exactStart, this.exactEnd, 0);
                    break;
                }
                if (this.nodes.Capacity < list.Count)
                {
                    this.nodes.Capacity = list.Count;
                }
                for (int i = 0; i < list.Count; i++)
                {
                    TriangleMeshNode triangleMeshNode = list[i] as TriangleMeshNode;
                    if (triangleMeshNode != null)
                    {
                        this.nodes.Add(triangleMeshNode);
                    }
                }
                ListPool <GraphNode> .Release(list);
            }
            else
            {
                if (this.nodes.Capacity < end - start)
                {
                    this.nodes.Capacity = end - start;
                }
                for (int j = start; j <= end; j++)
                {
                    TriangleMeshNode triangleMeshNode2 = nodes[j] as TriangleMeshNode;
                    if (triangleMeshNode2 != null)
                    {
                        this.nodes.Add(triangleMeshNode2);
                    }
                }
            }
            for (int k = 0; k < this.nodes.Count - 1; k++)
            {
                this.nodes[k].GetPortal(this.nodes[k + 1], this.left, this.right, false);
            }
            this.left.Add(this.exactEnd);
            this.right.Add(this.exactEnd);
        }
Esempio n. 26
0
 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);
     }
 }
Esempio n. 27
0
 protected virtual Vector3 UpdateTarget(RichFunnel fn)
 {
     this.buffer.Clear();
     Vector3 vector = this.tr.position;
     bool flag;
     vector = fn.Update(vector, this.buffer, 2, out this.lastCorner, out flag);
     if (flag && !this.waitingForPathCalc)
     {
         this.UpdatePath();
     }
     return vector;
 }
Esempio n. 28
0
        /** Use this for initialization.
         *
         * \param s Optionally provide in order to take tag penalties into account. May be null if you do not use a Seeker\
         * \param p Path to follow
         * \param mergePartEndpoints If true, then adjacent parts that the path is split up in will
         * try to use the same start/end points. For example when using a link on a navmesh graph
         * Instead of first following the path to the center of the node where the link is and then
         * follow the link, the path will be adjusted to go to the exact point where the link starts
         * which usually makes more sense.
         * \param simplificationMode The path can optionally be simplified. This can be a bit expensive for long paths.
         */
        public void Initialize(Seeker s, Path p, bool mergePartEndpoints, RichFunnel.FunnelSimplification simplificationMode)
        {
            if (p.error)
            {
                throw new System.ArgumentException("Path has an error");
            }

            List <GraphNode> nodes = p.path;

            if (nodes.Count == 0)
            {
                throw new System.ArgumentException("Path traverses no nodes");
            }

            seeker = s;
            // Release objects back to object pool
            // Yeah, I know, it's casting... but this won't be called much
            for (int i = 0; i < parts.Count; i++)
            {
                if (parts[i] is RichFunnel)
                {
                    ObjectPool <RichFunnel> .Release(parts[i] as RichFunnel);
                }
                else if (parts[i] is RichSpecial)
                {
                    ObjectPool <RichSpecial> .Release(parts[i] as RichSpecial);
                }
            }

            parts.Clear();
            currentPart = 0;

            // Initialize new

            //Break path into parts
            for (int i = 0; i < nodes.Count; i++)
            {
                if (nodes[i] is TriangleMeshNode)
                {
                    var        graph = AstarData.GetGraph(nodes[i]);
                    RichFunnel f     = ObjectPool <RichFunnel> .Claim().Initialize(this, graph);

                    f.funnelSimplificationMode = simplificationMode;

                    int  sIndex            = i;
                    uint currentGraphIndex = nodes[sIndex].GraphIndex;


                    for (; i < nodes.Count; i++)
                    {
                        if (nodes[i].GraphIndex != currentGraphIndex && !(nodes[i] is NodeLink3Node))
                        {
                            break;
                        }
                    }
                    i--;

                    if (sIndex == 0)
                    {
                        f.exactStart = p.vectorPath[0];
                    }
                    else
                    {
                        f.exactStart = (Vector3)nodes[mergePartEndpoints ? sIndex - 1 : sIndex].position;
                    }

                    if (i == nodes.Count - 1)
                    {
                        f.exactEnd = p.vectorPath[p.vectorPath.Count - 1];
                    }
                    else
                    {
                        f.exactEnd = (Vector3)nodes[mergePartEndpoints ? i + 1 : i].position;
                    }

                    f.BuildFunnelCorridor(nodes, sIndex, i);

                    parts.Add(f);
                }
                else if (NodeLink2.GetNodeLink(nodes[i]) != null)
                {
                    NodeLink2 nl = NodeLink2.GetNodeLink(nodes[i]);

                    int  sIndex            = i;
                    uint currentGraphIndex = nodes[sIndex].GraphIndex;

                    for (i++; i < nodes.Count; i++)
                    {
                        if (nodes[i].GraphIndex != currentGraphIndex)
                        {
                            break;
                        }
                    }
                    i--;

                    if (i - sIndex > 1)
                    {
                        throw new System.Exception("NodeLink2 path length greater than two (2) nodes. " + (i - sIndex));
                    }
                    else if (i - sIndex == 0)
                    {
                        //Just continue, it might be the case that a NodeLink was the closest node
                        continue;
                    }

                    RichSpecial rps = ObjectPool <RichSpecial> .Claim().Initialize(nl, nodes[sIndex]);

                    parts.Add(rps);
                }
            }
        }
Esempio n. 29
0
        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));
        }
Esempio n. 30
0
        public void Initialize(Seeker s, Path p, bool mergePartEndpoints, RichFunnel.FunnelSimplification simplificationMode)
        {
            if (p.error)
            {
                throw new ArgumentException("Path has an error");
            }
            List <GraphNode> path = p.path;

            if (path.Count == 0)
            {
                throw new ArgumentException("Path traverses no nodes");
            }
            this.seeker = s;
            for (int i = 0; i < this.parts.Count; i++)
            {
                RichFunnel  funnel  = this.parts[i] as RichFunnel;
                RichSpecial special = this.parts[i] as RichSpecial;
                if (funnel != null)
                {
                    Pathfinding.Util.ObjectPool <RichFunnel> .Release(ref funnel);
                }
                else if (special != null)
                {
                    Pathfinding.Util.ObjectPool <RichSpecial> .Release(ref special);
                }
            }
            this.parts.Clear();
            this.currentPart = 0;
            for (int j = 0; j < path.Count; j++)
            {
                if (path[j] is TriangleMeshNode)
                {
                    NavGraph   graph = AstarData.GetGraph(path[j]);
                    RichFunnel item  = Pathfinding.Util.ObjectPool <RichFunnel> .Claim().Initialize(this, graph);

                    item.funnelSimplificationMode = simplificationMode;
                    int  start      = j;
                    uint graphIndex = path[start].GraphIndex;
                    while (j < path.Count)
                    {
                        if ((path[j].GraphIndex != graphIndex) && !(path[j] is NodeLink3Node))
                        {
                            break;
                        }
                        j++;
                    }
                    j--;
                    if (start == 0)
                    {
                        item.exactStart = p.vectorPath[0];
                    }
                    else
                    {
                        item.exactStart = (Vector3)path[!mergePartEndpoints ? start : (start - 1)].position;
                    }
                    if (j == (path.Count - 1))
                    {
                        item.exactEnd = p.vectorPath[p.vectorPath.Count - 1];
                    }
                    else
                    {
                        item.exactEnd = (Vector3)path[!mergePartEndpoints ? j : (j + 1)].position;
                    }
                    item.BuildFunnelCorridor(path, start, j);
                    this.parts.Add(item);
                    continue;
                }
                if (NodeLink2.GetNodeLink(path[j]) != null)
                {
                    NodeLink2 nodeLink = NodeLink2.GetNodeLink(path[j]);
                    int       num5     = j;
                    uint      num6     = path[num5].GraphIndex;
                    j++;
                    while (j < path.Count)
                    {
                        if (path[j].GraphIndex != num6)
                        {
                            break;
                        }
                        j++;
                    }
                    j--;
                    if ((j - num5) > 1)
                    {
                        throw new Exception("NodeLink2 path length greater than two (2) nodes. " + (j - num5));
                    }
                    if ((j - num5) != 0)
                    {
                        RichSpecial special2 = Pathfinding.Util.ObjectPool <RichSpecial> .Claim().Initialize(nodeLink, path[num5]);

                        this.parts.Add(special2);
                    }
                }
            }
        }
Esempio n. 31
0
        /// <summary>Use this for initialization.</summary>
        /// <param name="seeker">Optionally provide in order to take tag penalties into account. May be null if you do not use a Seeker\</param>
        /// <param name="path">Path to follow</param>
        /// <param name="mergePartEndpoints">If true, then adjacent parts that the path is split up in will
        /// try to use the same start/end points. For example when using a link on a navmesh graph
        /// Instead of first following the path to the center of the node where the link is and then
        /// follow the link, the path will be adjusted to go to the exact point where the link starts
        /// which usually makes more sense.</param>
        /// <param name="simplificationMode">The path can optionally be simplified. This can be a bit expensive for long paths.</param>
        public void Initialize(Seeker seeker, Path path, bool mergePartEndpoints, bool simplificationMode)
        {
            if (path.error)
            {
                throw new System.ArgumentException("Path has an error");
            }

            List <GraphNode> nodes = path.path;

            if (nodes.Count == 0)
            {
                throw new System.ArgumentException("Path traverses no nodes");
            }

            this.seeker = seeker;
            // Release objects back to object pool
            // Yeah, I know, it's casting... but this won't be called much
            for (int i = 0; i < parts.Count; i++)
            {
                var funnelPart  = parts[i] as RichFunnel;
                var specialPart = parts[i] as RichSpecial;
                if (funnelPart != null)
                {
                    ObjectPool <RichFunnel> .Release(ref funnelPart);
                }
                else if (specialPart != null)
                {
                    ObjectPool <RichSpecial> .Release(ref specialPart);
                }
            }

            Clear();

            // Initialize new
            Endpoint = path.vectorPath[path.vectorPath.Count - 1];

            //Break path into parts
            for (int i = 0; i < nodes.Count; i++)
            {
                if (nodes[i] is TriangleMeshNode)
                {
                    var graph = AstarData.GetGraph(nodes[i]) as NavmeshBase;
                    if (graph == null)
                    {
                        throw new System.Exception("Found a TriangleMeshNode that was not in a NavmeshBase graph");
                    }

                    RichFunnel f = ObjectPool <RichFunnel> .Claim().Initialize(this, graph);

                    f.funnelSimplification = simplificationMode;

                    int  sIndex            = i;
                    uint currentGraphIndex = nodes[sIndex].GraphIndex;


                    for (; i < nodes.Count; i++)
                    {
                        if (nodes[i].GraphIndex != currentGraphIndex && !(nodes[i] is NodeLink3Node))
                        {
                            break;
                        }
                    }
                    i--;

                    if (sIndex == 0)
                    {
                        f.exactStart = path.vectorPath[0];
                    }
                    else
                    {
                        f.exactStart = (Vector3)nodes[mergePartEndpoints ? sIndex - 1 : sIndex].position;
                    }

                    if (i == nodes.Count - 1)
                    {
                        f.exactEnd = path.vectorPath[path.vectorPath.Count - 1];
                    }
                    else
                    {
                        f.exactEnd = (Vector3)nodes[mergePartEndpoints ? i + 1 : i].position;
                    }

                    f.BuildFunnelCorridor(nodes, sIndex, i);

                    parts.Add(f);
                }
                else if (NodeLink2.GetNodeLink(nodes[i]) != null)
                {
                    NodeLink2 nl = NodeLink2.GetNodeLink(nodes[i]);

                    int  sIndex            = i;
                    uint currentGraphIndex = nodes[sIndex].GraphIndex;

                    for (i++; i < nodes.Count; i++)
                    {
                        if (nodes[i].GraphIndex != currentGraphIndex)
                        {
                            break;
                        }
                    }
                    i--;

                    if (i - sIndex > 1)
                    {
                        throw new System.Exception("NodeLink2 path length greater than two (2) nodes. " + (i - sIndex));
                    }
                    else if (i - sIndex == 0)
                    {
                        //Just continue, it might be the case that a NodeLink was the closest node
                        continue;
                    }

                    RichSpecial rps = ObjectPool <RichSpecial> .Claim().Initialize(nl, nodes[sIndex]);

                    parts.Add(rps);
                }
                else if (!(nodes[i] is PointNode))
                {
                    // Some other graph type which we do not have support for
                    throw new System.InvalidOperationException("The RichAI movment script can only be used on recast/navmesh graphs. A node of type " + nodes[i].GetType().Name + " was in the path.");
                }
            }
        }