Inheritance: RichPathPart
        /// <summary>Traverses an off-mesh link</summary>
        protected virtual IEnumerator TraverseSpecial(RichSpecial link)
        {
            traversingOffMeshLink = true;
            // The current path part is a special part, for example a link
            // Movement during this part of the path is handled by the TraverseSpecial coroutine
            velocity2D = Vector3.zero;
            var offMeshLinkCoroutine = onTraverseOffMeshLink != null?onTraverseOffMeshLink(link) : TraverseOffMeshLinkFallback(link);

            yield return(StartCoroutine(offMeshLinkCoroutine));

            // Off-mesh link traversal completed
            traversingOffMeshLink = false;
            NextPart();

            // If a path completed during the time we traversed the special connection, we need to recalculate it
            if (delayUpdatePath)
            {
                delayUpdatePath = false;
                // 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?
                if (canSearch)
                {
                    SearchPath();
                }
            }
        }
Ejemplo n.º 2
0
        protected virtual IEnumerator TraverseSpecial(RichSpecial rs)
        {
            traversingSpecialPath = true;
            velocity2D            = Vector3.zero;

            var link = rs.nodeLink as AnimationLink;

            if (link == null)
            {
                Debug.LogError("Unhandled RichSpecial");
                yield break;
            }

            // Rotate character to face the correct direction
            // Magic number, should expose as variable
            while (Vector2.Angle(movementPlane.ToPlane(tr.forward), movementPlane.ToPlane(rs.first.forward)) > 5f)
            {
                RotateTowards(movementPlane.ToPlane(rs.first.forward), rotationSpeed * Time.deltaTime);
                yield return(null);
            }

            // Reposition
            tr.parent.position = tr.position;

            tr.parent.rotation = tr.rotation;
            tr.localPosition   = Vector3.zero;
            tr.localRotation   = Quaternion.identity;

            // Set up animation speeds
            if (rs.reverse && link.reverseAnim)
            {
                anim[link.clip].speed          = -link.animSpeed;
                anim[link.clip].normalizedTime = 1;
                anim.Play(link.clip);
                anim.Sample();
            }
            else
            {
                anim[link.clip].speed = link.animSpeed;
                anim.Rewind(link.clip);
                anim.Play(link.clip);
            }

            // Fix required for animations in reverse direction
            tr.parent.position -= tr.position - tr.parent.position;

            // Wait for the animation to finish
            yield return(new WaitForSeconds(Mathf.Abs(anim[link.clip].length / link.animSpeed)));

            traversingSpecialPath = false;
            NextPart();

            // If a path completed during the time we traversed the special connection, we need to recalculate it
            if (delayUpdatePath)
            {
                delayUpdatePath = false;
                UpdatePath();
            }
        }
Ejemplo n.º 3
0
        IEnumerator TraverseSpecial(RichSpecial rs)
        {
            traversingSpecialPath = true;
            velocity = Vector3.zero;

            var al = rs.nodeLink as AnimationLink;

            if (al == null)
            {
                Debug.LogError("Unhandled RichSpecial");
                yield break;
            }

            //Rotate character to face the correct direction
            while (!RotateTowards(rs.first.forward))
            {
                yield return(null);
            }

            //Reposition
            tr.parent.position = tr.position;

            tr.parent.rotation = tr.rotation;
            tr.localPosition   = Vector3.zero;
            tr.localRotation   = Quaternion.identity;

            //Set up animation speeds
            if (rs.reverse && al.reverseAnim)
            {
                anim[al.clip].speed          = -al.animSpeed;
                anim[al.clip].normalizedTime = 1;
                anim.Play(al.clip);
                anim.Sample();
            }
            else
            {
                anim[al.clip].speed = al.animSpeed;
                anim.Rewind(al.clip);
                anim.Play(al.clip);
            }

            //Fix required for animations in reverse direction
            tr.parent.position -= tr.position - tr.parent.position;

            //Wait for the animation to finish
            yield return(new WaitForSeconds(Mathf.Abs(anim[al.clip].length / al.animSpeed)));

            traversingSpecialPath = false;
            NextPart();

            //If a path completed during the time we traversed the special connection, we need to recalculate it
            if (delayUpdatePath)
            {
                delayUpdatePath = false;
                UpdatePath();
            }
        }
Ejemplo n.º 4
0
        protected virtual IEnumerator TraverseSpecial(RichSpecial rs)
        {
            this.traversingSpecialPath = true;
            this.velocity2D            = Vector3.zero;
            AnimationLink link = rs.nodeLink as AnimationLink;

            if (link == null)
            {
                Debug.LogError("Unhandled RichSpecial");
                yield break;
            }
            while (Vector2.Angle(this.movementPlane.ToPlane(this.rotationIn2D ? this.tr.up : this.tr.forward), this.movementPlane.ToPlane(rs.first.forward)) > 5f)
            {
                this.RotateTowards(this.movementPlane.ToPlane(rs.first.forward), this.rotationSpeed * Time.deltaTime);
                yield return(null);
            }
            this.tr.parent.position = this.tr.position;
            this.tr.parent.rotation = this.tr.rotation;
            this.tr.localPosition   = Vector3.zero;
            this.tr.localRotation   = Quaternion.identity;
            if (rs.reverse && link.reverseAnim)
            {
                this.anim[link.clip].speed          = -link.animSpeed;
                this.anim[link.clip].normalizedTime = 1f;
                this.anim.Play(link.clip);
                this.anim.Sample();
            }
            else
            {
                this.anim[link.clip].speed = link.animSpeed;
                this.anim.Rewind(link.clip);
                this.anim.Play(link.clip);
            }
            this.tr.parent.position -= this.tr.position - this.tr.parent.position;
            yield return(new WaitForSeconds(Mathf.Abs(this.anim[link.clip].length / link.animSpeed)));

            this.traversingSpecialPath = false;
            this.NextPart();
            if (this.delayUpdatePath)
            {
                this.delayUpdatePath = false;
                this.UpdatePath();
            }
            yield break;
            yield break;
        }
Ejemplo n.º 5
0
        private IEnumerator TraverseSpecial(RichSpecial rs)
        {
            this.traversingSpecialPath = true;
            this.velocity = Vector3.zero;
            AnimationLink al = rs.nodeLink as AnimationLink;

            if (al == null)
            {
                Debug.LogError("Unhandled RichSpecial");
                yield break;
            }
            while (!this.RotateTowards(rs.first.forward))
            {
                yield return(null);
            }
            this.tr.parent.position = this.tr.position;
            this.tr.parent.rotation = this.tr.rotation;
            this.tr.localPosition   = Vector3.zero;
            this.tr.localRotation   = Quaternion.identity;
            if (rs.reverse && al.reverseAnim)
            {
                this.anim[al.clip].speed          = -al.animSpeed;
                this.anim[al.clip].normalizedTime = 1f;
                this.anim.Play(al.clip);
                this.anim.Sample();
            }
            else
            {
                this.anim[al.clip].speed = al.animSpeed;
                this.anim.Rewind(al.clip);
                this.anim.Play(al.clip);
            }
            this.tr.parent.position -= this.tr.position - this.tr.parent.position;
            yield return(new WaitForSeconds(Mathf.Abs(this.anim[al.clip].length / al.animSpeed)));

            this.traversingSpecialPath = false;
            this.NextPart();
            if (this.delayUpdatePath)
            {
                this.delayUpdatePath = false;
                this.UpdatePath();
            }
            yield break;
        }
Ejemplo n.º 6
0
        // Token: 0x06002180 RID: 8576 RVA: 0x0018EA3B File Offset: 0x0018CC3B
        protected virtual IEnumerator TraverseSpecial(RichSpecial link)
        {
            this.traversingOffMeshLink = true;
            this.velocity2D            = Vector3.zero;
            IEnumerator routine = (this.onTraverseOffMeshLink != null) ? this.onTraverseOffMeshLink(link) : this.TraverseOffMeshLinkFallback(link);

            yield return(base.StartCoroutine(routine));

            this.traversingOffMeshLink = false;
            this.NextPart();
            if (this.delayUpdatePath)
            {
                this.delayUpdatePath = false;
                if (this.canSearch)
                {
                    this.SearchPath();
                }
            }
            yield break;
        }
Ejemplo n.º 7
0
        // Token: 0x06002181 RID: 8577 RVA: 0x0018EA51 File Offset: 0x0018CC51
        protected IEnumerator TraverseOffMeshLinkFallback(RichSpecial link)
        {
            float duration  = (this.maxSpeed > 0f) ? (Vector3.Distance(link.second.position, link.first.position) / this.maxSpeed) : 1f;
            float startTime = Time.time;

            for (;;)
            {
                Vector3 vector = Vector3.Lerp(link.first.position, link.second.position, Mathf.InverseLerp(startTime, startTime + duration, Time.time));
                if (this.updatePosition)
                {
                    this.tr.position = vector;
                }
                else
                {
                    this.simulatedPosition = vector;
                }
                if (Time.time >= startTime + duration)
                {
                    break;
                }
                yield return(null);
            }
            yield break;
        }
        /// <summary>
        /// Fallback for traversing off-mesh links in case <see cref="onTraverseOffMeshLink"/> is not set.
        /// This will do a simple linear interpolation along the link.
        /// </summary>
        protected IEnumerator TraverseOffMeshLinkFallback(RichSpecial link)
        {
            float duration  = maxSpeed > 0 ? Vector3.Distance(link.second.position, link.first.position) / maxSpeed : 1;
            float startTime = Time.time;

            while (true)
            {
                var pos = Vector3.Lerp(link.first.position, link.second.position, Mathf.InverseLerp(startTime, startTime + duration, Time.time));
                if (updatePosition)
                {
                    tr.position = pos;
                }
                else
                {
                    simulatedPosition = pos;
                }

                if (Time.time >= startTime + duration)
                {
                    break;
                }
                yield return(null);
            }
        }
Ejemplo n.º 9
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);
                }
            }
        }
Ejemplo n.º 10
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);
                    }
                }
            }
        }
Ejemplo n.º 11
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);
                    }
                }
            }
        }
Ejemplo n.º 12
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);
     }
 }
Ejemplo n.º 13
0
 private IEnumerator TraverseSpecial(RichSpecial rs)
 {
     RichAI.<TraverseSpecial>c__Iterator2 <TraverseSpecial>c__Iterator = new RichAI.<TraverseSpecial>c__Iterator2();
     <TraverseSpecial>c__Iterator.rs = rs;
     <TraverseSpecial>c__Iterator.<$>rs = rs;
     <TraverseSpecial>c__Iterator.<>f__this = this;
     return <TraverseSpecial>c__Iterator;
 }
Ejemplo n.º 14
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);
                }
            }
        }
Ejemplo n.º 15
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.");
                }
            }
        }
Ejemplo n.º 16
0
		IEnumerator TraverseSpecial (RichSpecial rs) {
			traversingSpecialPath = true;
			velocity = Vector3.zero;
			
			AnimationLink al = rs.nodeLink as AnimationLink;
			if (al == null) {
				Debug.LogError ("Unhandled RichSpecial");
				yield break;
			}
			
			//Rotate character to face the correct direction
			while (!RotateTowards(rs.first.forward)) yield return null;
			
			//Reposition
			tr.parent.position = tr.position;
			
			tr.parent.rotation = tr.rotation;
			tr.localPosition = Vector3.zero;
			tr.localRotation = Quaternion.identity;
			
			//Set up animation speeds
			if (rs.reverse && al.reverseAnim) {
				anim[al.clip].speed = -al.animSpeed;
				anim[al.clip].normalizedTime = 1;
				anim.Play(al.clip);
				anim.Sample();
			} else {
				anim[al.clip].speed = al.animSpeed;
				anim.Rewind(al.clip);
				anim.Play(al.clip);
			}
			
			//Fix required for animations in reverse direction
			tr.parent.position -= tr.position-tr.parent.position;
			
			//Wait for the animation to finish
			yield return new WaitForSeconds(Mathf.Abs(anim[al.clip].length/al.animSpeed));
			
			traversingSpecialPath = false;
			NextPart ();
			
			//If a path completed during the time we traversed the special connection, we need to recalculate it
			if (delayUpdatePath) {
				delayUpdatePath = false;
				UpdatePath();
			}
		}
Ejemplo n.º 17
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);
                    }
                }
            }
        }