/// <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); }
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); }
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); }
/// <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()); }
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; } } }