Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. 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


    Feb 11, 2020
    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:

    Same test vs. CapsuleCollider:

    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,;
    18.         }
    19.         else
    20.         {
    21.             Debug.DrawRay(origin, direction * distance,;
    22.         }
    23.     }
    24. }
  2. Eric_ECG


    Feb 11, 2020
    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.


    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


    Feb 11, 2020
    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


    Feb 11, 2020
    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.