예제 #1
0
    /// <summary>
    /// Checks if the next waypoint is positioned on the ground and can thus be walked on
    /// </summary>
    /// <param name="terrainLayers"></param>
    /// <returns></returns>
    public bool IsWaypointOnGround(LayerMask terrainLayers)
    {
        bool isOnGround;


        isOnGround = Physics2D.Raycast(path.vectorPath[currentWaypoint], Vector3.down, 1.5f, terrainLayers).collider != null;


        if (ai.showDetectors)
        {
            DebugDrawPhysics.DebugDrawCircle(path.vectorPath[currentWaypoint], 0.25f, isOnGround ? Color.green : Color.red, 1f / ai.checksPerSecond);
        }

        return(isOnGround);
    }
예제 #2
0
    protected bool CheckForGround(bool debug)
    {
        Vector2 cStart     = (Vector2)feet.transform.position + 0.5f * Vector2.up;
        Vector2 cDirection = Vector2.down;
        float   cRadius    = feet.GetWidth() / 2;
        float   cDistance  = 0.5f + (transform.position - feet.transform.position).magnitude + feet.GetWidth() / 2f;

        // Using circle cast because we don't want the characters jumping on tiny inconsistencies in colliders
        RaycastHit2D hit    = Physics2D.CircleCast(cStart, cRadius, cDirection, cDistance, groundLayer);
        var          didHit = hit.collider != null;

        // Visual for the colliders
        if (debug)
        {
            DebugDrawPhysics.DebugDrawCircleCast(cStart, cRadius, cDirection, cDistance,
                                                 didHit ? Color.red : Color.green);
        }
        return(didHit);
    }
예제 #3
0
        public bool IsWaypointOnGround(LayerMask terrainLayers)
        {
            bool isOnGround;

            if (is2D)
            {
                isOnGround = Physics2D.Raycast(path.vectorPath[currentWaypoint], Vector3.down, 1.5f, terrainLayers).collider != null;
            }
            else
            {
                isOnGround = Physics.Raycast(path.vectorPath[currentWaypoint], Vector3.down, 1.5f, terrainLayers);
            }

            if (ai.verboseDebug)
            {
                DebugDrawPhysics.DebugDrawCircle(path.vectorPath[currentWaypoint], 0.25f, isOnGround ? Color.green : Color.red, 1f / ai.thinkPerSecond);
            }

            return(isOnGround);
        }
예제 #4
0
        /// <summary>
        /// Follows a path by running and jumping
        ///
        /// returns true if reached end of path
        /// </summary>
        bool FollowPath()
        {
            if (!pathfinding.IsOnPath())
            {
                pathfinding.SetPathUnvalid();
                if (verboseDebug)
                {
                    Debug.Log(name + ": " + state + ": I was no longer on my path so requested a new one");
                }
                return(false);
            }
            //Find next waypoint that is on the ground. If the last one is in the air then we should jump to it
            pathfinding.FindNextVisibleGroundedWaypoint(terrainLayers);

            //Direction to the next waypoint
            Vector3 dist = (pathfinding.GetCurrentWaypoint() - position);
            Vector3 dir  = dist.normalized;

            //If verbose is on then we can draw some helper symbols to see what the character is currently trying to do
            if (verboseDebug)
            {
                DebugDrawPhysics.DebugDrawCircle(pathfinding.GetCurrentWaypoint(), 1, Color.yellow);
            }

            //If there's a hole in the ground and the waypoint is not below us then jump
            doJump = DetectHolesInGround() && dir.y >= 0;

            //---Run---
            if (dir.x > 0)
            {
                run = 1;
                //Jump if we need to move up, double jumps will occur when we reach the max of the parabola and thus the upwards velocity is zero
                if (dist.y > 1 &&    //The next waypoint is at least one meter up
                    Vector3.Angle(Vector3.right, dir) > angleToJump &&
                    velocity.y <= 0) //A velocity zero we reached the top of the jump parabola
                {
                    doJump = true;
                }
            }
            else
            {
                run = -1;
                //Jump if we need to move up
                if (dist.y > 1 &&
                    Vector3.Angle(Vector3.left, dir) > angleToJump &&
                    velocity.y <= 0)
                {
                    doJump = true;
                }
            }

            //If we have a low obstacle then we should try jumping
            //Note that we will jump regardless of whether we detect an upper obstacle or not
            //We will only jump when we do not have upwards velocity so that we do not waste any double jumps
            if (isDetectingLowObstacle && velocity.y <= 0)
            {
                doJump = true;
            }
            //Check if we are close enough to the next waypoint
            //If we are, proceed to follow the next waypoint
            return(pathfinding.SelectNextWaypointIfCloseEnough());
        }
예제 #5
0
        public void DetectObstacles(float angle = 0)
        {
            //if (run == 0) return;
            Vector2 direction;

            if (run > 0)
            {
                direction        = Vector2.right;
                upperFeelerPos.x = Mathf.Abs(upperFeelerPos.x);
                lowerFeelerPos.x = Mathf.Abs(lowerFeelerPos.x);
            }
            else
            {
                direction        = Vector2.left;
                upperFeelerPos.x = -Mathf.Abs(upperFeelerPos.x);
                lowerFeelerPos.x = -Mathf.Abs(lowerFeelerPos.x);
            }
            if (is2D)
            {
                RaycastHit2D hit = Physics2D.BoxCast(position + upperFeelerPos, upperFeelerSize, angle, direction, 0, feelerDetectMask);
                if (hit.collider != null)
                {
                    isDetectingHighObstacle = true;
                    DebugDrawPhysics.DebugDrawBoxCast(position + upperFeelerPos, upperFeelerSize, angle, direction, 0, Color.red);
                }
                else
                {
                    DebugDrawPhysics.DebugDrawBoxCast(position + upperFeelerPos, upperFeelerSize, angle, direction, 0, Color.green);
                    isDetectingHighObstacle = false;
                }

                hit = Physics2D.BoxCast(position + lowerFeelerPos, lowerFeelerSize, angle, direction, 0, feelerDetectMask);
                if (hit.collider != null)
                {
                    DebugDrawPhysics.DebugDrawBoxCast(position + lowerFeelerPos, lowerFeelerSize, angle, direction, 0, Color.red);
                    isDetectingLowObstacle = true;
                }
                else
                {
                    DebugDrawPhysics.DebugDrawBoxCast(position + lowerFeelerPos, lowerFeelerSize, angle, direction, 0, Color.green);
                    isDetectingLowObstacle = false;
                }
            }
            else
            {
                //There's a difference between how 2D and 3D handles boxcast. In3D the boxcast cannot initially touch the object or it will return false
                //while in 2D it will return true if there's an object present in the cast. Therefore we must set the initial box inside the character
                //where we are sure to not hit any terrain
                RaycastHit hit;
                Vector3    upperfeelerSize3D = upperFeelerSize;
                Vector3    upperfeelerPos3D  = upperFeelerPos;
                upperfeelerSize3D.z = 1;
                Vector3 lowerfeelerSize3D = lowerFeelerSize;
                Vector3 lowerfeelerPos3D  = lowerFeelerPos;
                lowerfeelerSize3D.z = 1;

                //Upper box
                float distance = Mathf.Abs(upperfeelerPos3D.x);
                upperfeelerPos3D.x = 0;
                Physics.BoxCast(transform.position + upperfeelerPos3D, upperfeelerSize3D / 2, direction, out hit, Quaternion.Euler(0, 0, angle), distance, feelerDetectMask);
                if (hit.collider != null)
                {
                    isDetectingHighObstacle = true;
                    DebugDrawPhysics.DebugDrawBoxCast(transform.position + upperfeelerPos3D, upperFeelerSize, angle, direction, distance, Color.red);
                }
                else
                {
                    DebugDrawPhysics.DebugDrawBoxCast(transform.position + upperfeelerPos3D, upperFeelerSize, angle, direction, distance, Color.green);
                    isDetectingHighObstacle = false;
                }

                //Lower box
                distance           = Mathf.Abs(lowerfeelerPos3D.x);
                lowerfeelerPos3D.x = 0;
                Physics.BoxCast(transform.position + lowerfeelerPos3D, lowerFeelerSize / 2, direction, out hit, Quaternion.Euler(0, 0, angle), distance, feelerDetectMask);

                if (hit.collider != null)
                {
                    DebugDrawPhysics.DebugDrawBoxCast(transform.position + lowerfeelerPos3D, lowerFeelerSize, angle, direction, distance, Color.red);
                    isDetectingLowObstacle = true;
                }
                else
                {
                    DebugDrawPhysics.DebugDrawBoxCast(transform.position + lowerfeelerPos3D, lowerFeelerSize, angle, direction, distance, Color.green);
                    isDetectingLowObstacle = false;
                }
            }
        }