private bool CheckCanClimbStaircase(float horzMoveDir, float stepHeight, float stepDepth, out SurfaceContact staircaseContact) { staircaseContact = null; if (frameContacts.Count == 0) { return(false); } var circleCollider = collider2D as CircleCollider2D; var center = ( Vector2 )circleCollider.bounds.center; var horzMoveDirVector = new Vector2(horzMoveDir, 0); // Seek forward for obstacle to climb on. var steepestContact = frameContacts.WithMin(c => Vector2.Dot(c.Normal, horzMoveDirVector)); if (Vector2.Dot(steepestContact.Normal, horzMoveDirVector) >= 0 || IsWalkable(steepestContact.Normal)) { return(false); } staircaseContact = steepestContact; // Cast up. Debug.DrawRay(center, Vector2.up * stepHeight, Color.cyan); var hit = Spatial.CircleCastFiltered( center, circleCollider.radius, Vector2.up, stepHeight, h => h.rigidbody == this.rigidbody2D, contactsLayerMask ); if (hit.collider != null) { Debug.DrawRay(hit.point, hit.normal * 0.1f, Color.red); return(false); } center += Vector2.up * stepHeight; // Cast forward. Debug.DrawRay(center, horzMoveDirVector * stepDepth, Color.cyan); hit = Spatial.CircleCastFiltered( center, circleCollider.radius, horzMoveDirVector, stepDepth, h => h.rigidbody == this.rigidbody2D, contactsLayerMask ); if (hit.collider != null) { Debug.DrawRay(hit.point, hit.normal * 0.1f, Color.red); return(false); } return(true); }