Search Unity

Question CapsuleCast is broken?

Discussion in 'Scripting' started by Lesnikus5, Oct 22, 2021.

  1. Lesnikus5

    Lesnikus5

    Joined:
    May 20, 2016
    Posts:
    131
    The documentation says that: "The capsule is defined by the two spheres with radius around point1 and point2, which form the two ends of the capsule." But when I set point1 and point2 vertically on top of each other, the capsule never starts at point positions. If the direction is dir = Vector3.down, then the capsule is much lower. If dir = Vector3.up, then much higher. The capsule is always vertically offset from the starting points. Why it happens?

    Code (CSharp):
    1.  
    2.         public CapsuleCollider capsule;
    3.         public LayerMask notWalkable;
    4.         public Transform p1;
    5.         public Transform p2;
    6.         public Vector3 dir;
    7.  
    8.         private void FixedUpdate()
    9.         {
    10.             CheckGround();
    11.         }
    12.  
    13.         public bool isGrounded = false;
    14.         RaycastHit hitInfo;
    15.  
    16.         void CheckGround()
    17.         {
    18.             float groundCheckDistance = p2.position.y - p1.position.y;
    19.  
    20.             if (Physics.CapsuleCast(p1.position, p2.position, capsule.radius, dir, out hitInfo, groundCheckDistance, ~notWalkable, QueryTriggerInteraction.Ignore))
    21.             {
    22.                 isGrounded = true;
    23.             }
    24.             else
    25.             {
    26.                 isGrounded = false;
    27.             }
    28.  
    29.             Debug.Log("p1.y= " + p1.position.y);
    30.             Debug.Log("p2.y= " + p2.position.y);
    31.             Debug.Log("groundCheckDistance= " + groundCheckDistance);
    32.             Debug.Log("isGrounded= " + isGrounded);
    33.         }
    34.  
     
    Last edited: Oct 22, 2021
  2. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,647
    What exactly are you trying to do? Shooting a CapsuleCast up or down sounds pointless when your points are on top of the other. The capsule always starts in between the two points, and shoots into your direction.

    upload_2021-10-22_9-22-30.png
     
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    p1, p2 and radius define the capsule (the black part). Direction and distance define the movement in the dotted red part (although NOT p1/p2 as you labelled them).

    Your "groundCheckDistance" are set as the distance between p1/p2 which doesn't make sense from your diagram. It's simply how far you want the capsule to move which isn't related to the distance between the ends of the capsule unless you're always scanning down by the capsule height in this case.

    If those p1/p2 are identical then I have no idea what 3D physics will do but in that case, why not use a SphereCast because that's what you seem to want then.
     
  4. Lesnikus5

    Lesnikus5

    Joined:
    May 20, 2016
    Posts:
    131
    Damn, my posts for some reason require approval from the moderator, I hope I don't have to wait 2 days for confirmation. Deleted the previous message.

    I am trying to make a levitating capsule. To do this, you need to shoot the capsule down, as in the picture:

    1.jpg
    I will repost the picture again, otherwise the previous message was visible only to the moderators.

    No, I don't need a SphereCast. I'm just trying to find the highest point on the ground below the character and gently raise character above it (levitation) using AddForсe. In the picture, I wanted to depict the character's Сapsule Сollider in black, and the Сapsule Сast that I want to get with a red dotted line.

    The points p1/p2 really do not correspond to reality and I have to do various calculations to make it look like in the picture:

    Code (CSharp):
    1.  
    2.  
    3.         bool isGrounded = false;
    4.         float groundHeight;
    5.         Vector3 groundNormal;
    6.         float groundCheckDistance;
    7.         float groundCheckDistanceToHit;
    8.  
    9.         void CheckGround()
    10.         {
    11.             RaycastHit groundHit;
    12.  
    13.             groundCheckDistance = capsule.center.y - (capsule.height / 2) + capsule.radius;
    14.             float pointBottomHeight = rb.position.y + groundCheckDistance + capsule.radius;
    15.             float pointUpperHeight = pointBottomHeight + groundCheckDistance;
    16.  
    17.             Vector3 pointBottom = new Vector3(rb.position.x, pointBottomHeight, rb.position.z);
    18.             Vector3 pointUpper = new Vector3(rb.position.x, pointUpperHeight, rb.position.z);
    19.  
    20.             if (Physics.CapsuleCast(pointBottom, pointUpper, capsule.radius, Vector3.down, out groundHit, groundCheckDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore))
    21.             {
    22.                 isGrounded = true;
    23.                 groundHeight = groundHit.point.y;
    24.                 groundNormal = groundHit.normal;
    25.                 groundCheckDistanceToHit = Mathf.Abs(groundHit.point.y - (rb.position.y + groundCheckDistance));
    26.             }
    27.             else
    28.             {
    29.                 isGrounded = false;
    30.                 groundHeight = rb.position.y;
    31.                 groundNormal = Vector3.up;
    32.             }
    33.         }
    34.  
     
    Last edited: Oct 22, 2021
  5. Lesnikus5

    Lesnikus5

    Joined:
    May 20, 2016
    Posts:
    131
    Oh, it turns out SphereCast does not create a single sphere, but expands it into a capsule using maxDistance! It changes everything! I was confused by function name and I thought that SphereCast can only create strict single spheres, while CapsuleCast create a capsule between two points. Now I realized that CapsuleCast creates a capsule and stretches it sideways (not vertically) to a specified length, and SphereCast creates a sphere and stretches it into a capsule to a specified length.

    I think that the documentation does not give a sufficient understanding of the work of CapsuleCast and SphereCast, and if what I formulated above were directly stated in the documentation, everything would be much clearer.

    So you're right, SphereCast suits me perfectly, the problem was in understanding the essence of the method.
     
    Last edited: Oct 26, 2021
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    It doesn't "stretch" shapes at all.

    A sphere isn't stretched into a capsule. The word "cast" means the shape is swept through space, this is what all "casts" are i.e. BoxCast, Raycast, SphereCast etc. A Sphere isn't stretched into a capsule, a sphere is cast through space. Sure, it covers a region you could call a capsule but that's just the region it traverses.

    A raycast is a point that is swept through space.

    A capsule does the same. It's a capsule defined by your two points and the radius, swept in the direction and distance you specify.
     
  7. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,647
    I don't think it's entirely true what you said, SphereCast and CapsuleCast basically just do a Raycast, but instead of a point, they use either a Sphere or Capsule for hit detection. Basically, instead of shooting a laser, you're shooting a ball or a capsule, and returning the first thing hit. When shooting a CapsuleCast straight down, you're only really going to get collision on the round bottom of your Capsule, which would be no different than shooting a Sphere straight down.