Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug Physics.Raycast against CharacterController is broken/bugged/unreliable in 2021?

Discussion in 'Physics' started by Eric_ECG, May 5, 2023.

  1. Eric_ECG

    Eric_ECG

    Joined:
    Feb 11, 2020
    Posts:
    4
    Using Unity 2021.3.15f1

    Started doing some Physics.Raycast to try to find characters in the world, seems like the most standard technique for testing line of sight, steering, etc...

    All of our characters have a CharacterController attached

    CharacterController inherits from Collider so I would expect Physics.Raycast to behave the same against a CapsuleCollider vs CharacterController.

    Was getting unexpected results so started debugging and was shocked to find that Physics.Raycast behaves unexpectedly vs CharacterControllers. It's not at all reliable to use, it will miss when it should hit, and when it does hit the point it returns will always be inside the CharacterController rather than on the surface!?!?

    Simplest possible test of Phyics.Raycast vs CharacterController:
    upload_2023-5-5_9-27-49.png

    Same test vs. CapsuleCollider:
    upload_2023-5-5_9-35-46.png

    I suppose I have to work around this issue by attaching an additional CapsuleCollider to all of my CharacterControllers to raycast against... but this is something a massive number of games probably encounter, how is this problem not better documented!?

    After searching the forums it appears in previous Unity versions Physics.Raycast ignored CharacterControllers completely, which I would honestly much prefer compared to the current functionality where it pretends to work but returns invalid information.

    Anyone else experienced this and worked around it? Would also love to hear from a Unity dev on this.

    Here is the test code used in the above screen shots:
    Code (CSharp):
    1. public class RayTest : MonoBehaviour
    2. {
    3.     private void Update()
    4.     {
    5.         Vector3 origin = transform.position;
    6.         Vector3 direction = transform.forward;
    7.         float distance = 2.0f;
    8.         bool hit = Physics.Raycast(
    9.             origin,
    10.             direction,
    11.             out RaycastHit info,
    12.             distance,
    13.             Physics.AllLayers,
    14.             QueryTriggerInteraction.Ignore);
    15.         if (hit)
    16.         {
    17.             Debug.DrawRay(origin, direction * info.distance, Color.green);
    18.         }
    19.         else
    20.         {
    21.             Debug.DrawRay(origin, direction * distance, Color.red);
    22.         }
    23.     }
    24. }
     
  2. Eric_ECG

    Eric_ECG

    Joined:
    Feb 11, 2020
    Posts:
    4
    Some further testing...

    Tests uses a standard 2m x 0.5m CharacterController

    This controller seems to have an exactly 0.1m think layer surrounding it where all raycasts miss.

    upload_2023-5-5_9-46-20.png

    Green wire is the CharacterController, scaled a capsule mesh renderer to have a 0.4m radius (0.8m diameter)

    You can see the raycasts are behaving exactly if they were being preformed against the 0.1m smaller capsule.
     
  3. Eric_ECG

    Eric_ECG

    Joined:
    Feb 11, 2020
    Posts:
    4
    Tested some arbitrarily sized CharacterControllers
    3m x 0.65m capsule has a 0.13m "miss layer"
    3m x 1m has a 0.2m "miss layer"

    So it seems that raycasts against a CharacterController are always being performed against a capsule that is approximately 20% smaller.

    Also noticed that the 0.1m "miss layer" on the 2m x 0.5m capsule was almost equal the CharacterControllers Skin Width which was set to 0.08m, so I thought that might have something to do with it... reduced to 0.0001 and had no effect on the issue.
     
  4. Eric_ECG

    Eric_ECG

    Joined:
    Feb 11, 2020
    Posts:
    4
    I ended up writing a script that attaches a CapsuleCollider and sizes it to match the CharacterController and that seems to do what I need. CharacterController handles collisions while moving and CapsuleCollider gives me something to ray cast against.

    No idea how hacky this is and if it might have other knock ons... but so far so good.
     
    titch_stewart likes this.
  5. titch_stewart

    titch_stewart

    Joined:
    Feb 10, 2014
    Posts:
    2
    This is what I've ended up doing. Thanks for the tip
     
  6. exhuman

    exhuman

    Joined:
    Sep 27, 2019
    Posts:
    5
    For anyone else finding this thread through search engines, this is indeed expected behaviour. According to documentation: